bzoj4003

http://www.lydsy.com/JudgeOnline/problem.php?id=4003

可合并堆。

每个点都有一个小根堆,记住可以到这个点的骑士有哪些,以战斗力为关键字。

从底层到顶层不断合并,然后不断取出战斗力的最小值,如果小于防御值,则去掉最小值。

操作可以打标记。

我用了左偏树。

左偏树太不熟悉了,打错了2个地方,去了皮的大土豆~OTATO

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
 
using namespace std;

typedef long long LL;
typedef double DB;
typedef complex<DB> CP;

#define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define fill(a,l,r,v) fill(a+l,a+r+1,v)
#define re(i,a,b)  for(i=(a);i<=(b);i++)
#define red(i,a,b) for(i=(a);i>=(b);i--)
#define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define p_b(a) push_back(a)
#define SF scanf
#define PF printf
#define two(k) (1<<(k))

template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}

const DB EPS=1e-9;
inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
const DB Pi=acos(-1.0);

inline int gint()
  {
        int res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }
inline LL gll()
  {
      LL res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }

const int maxN=300000;

int N,M;
vector<int> son[maxN+100];
vector<int> Q[maxN+100];
int f[maxN+100],dep[maxN+100],a[maxN+100];
LL h[maxN+100],v[maxN+100];
int c[maxN+100];
LL s[maxN+100];

struct Tnode
  {
      Tnode *l,*r;
      LL v,mu,add;int id,dis;
      inline Tnode(LL _v=0,LL _mu=1,LL _add=0,int _id=0,int _dis=0){l=0;r=0;v=_v;mu=_mu;add=_add;id=_id;dis=_dis;}
      inline int ldis(){return l?l->dis:0;}
      inline int rdis(){return r?r->dis:0;}
      inline void down()
        {
            if(mu==1 && add==0)return;
            if(l)l->v=l->v*mu+add,l->add=mu*l->add+add,l->mu=mu*l->mu;
            if(r)r->v=r->v*mu+add,r->add=mu*r->add+add,r->mu=mu*r->mu;
            mu=1;add=0;
        }
  };

inline Tnode  *uni(Tnode *a,Tnode *b)
  {
      if(!a)return b;
      if(!b)return a;
      a->down();
        b->down();
      if(a->v > b->v)swap(a,b);
      a->r=uni(a->r,b);
      if(a->ldis() < a->rdis())swap(a->l,a->r);
      a->dis=a->rdis()+1;
      return a;
  }

Tnode mem[maxN+100];
Tnode *rt[maxN+100];

int ge[maxN+100],out[maxN+100];

int main()
  {
      /*freopen("bzoj4003.in","r",stdin);
        freopen("bzoj4003.out","w",stdout);*/
        int i,j;
        N=gint();M=gint();
        re(i,1,N)h[i]=gll();
        re(i,2,N)f[i]=gll(),a[i]=gint(),v[i]=gll(),son[f[i]].p_b(i);
        re(i,1,M)s[i]=gll(),c[i]=gint(),Q[c[i]].p_b(i);
        re(i,1,N)dep[i]=dep[f[i]]+1;
        re(i,1,M)mem[i]=Tnode(s[i],1,0,i,1);
        red(i,N,1)
          {
              re(j,0,int(son[i].size())-1)
                  {
                      int ch=son[i][j];
                        rt[i]=uni(rt[i],rt[ch]);
                    }
                re(j,0,int(Q[i].size())-1)
                  {
                      int t=Q[i][j];
                      rt[i]=uni(rt[i],&mem[t]);
                  }
                while(rt[i] && rt[i]->v<h[i])
                  {
                      ge[i]++;
                      int t=rt[i]->id;
                      out[t]=dep[c[t]]-dep[i];
                      rt[i]->down();////////////////////////////////////////////注意这里要down
                      rt[i]=uni(rt[i]->l,rt[i]->r);
                  }
                if(rt[i])
                  if(a[i]==0)
                    rt[i]->v+=v[i],rt[i]->add+=v[i];
                  else
                    rt[i]->v*=v[i],rt[i]->mu*=v[i],rt[i]->add*=v[i];
            }
        while(rt[1])
          {
              int t=rt[1]->id;
              out[t]=dep[c[t]];
              rt[1]->down();////////////////////////////////////////////注意这里要down
              rt[1]=uni(rt[1]->l,rt[1]->r);
          }
        re(i,1,N)PF("%d\n",ge[i]);
        re(i,1,M)PF("%d\n",out[i]);
        return 0;
  }
View Code

然后有另外一种不适用这题的方法。

我们发现,如果某个骑士的初始战斗力为x,那么骑士在当前点的战斗力为ax+b,其实a和b只跟出发点和当前点的位置有关,与x无关。

并且我们发现a一定是正数。

类似于LCA,

to[i][j]表示i号点跳2^j次到的点。

jump[i][j]表示,这是一个pair,表示一个初始位置在i号点的骑士的初始战斗力为x,跳2^j次后,战斗力变成jump[i][j].fi*x+jump[i][j].se,其实jump[i][j].fi和jump[i][j].se只和i,有关,与x无关。

minx[i][j]表示,一个初始位置在i号点的骑士的初始战斗力为x,想要跳2^j次,x至少要为minx[i][j]。

容易发现x[i][j]随着j的递增而递增,有单调性。

可以用nlogn的时间求出。

然后对于初始位置在i的骑士,记其初始战斗力为x,二分j,判断x与minx[i][j]的大小关系即可。

但是这道题不适用的地方在于:

(1)MLE

(2)题目保证“任何时候骑士战斗力值的绝对值不超过 10^18”,不是"骑士跑到到根战斗力值的绝对值不超过 10^18“,这样很容易就爆longlong了。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj
 
using namespace std;

typedef long long LL;
typedef double DB;
typedef pair<LL,LL> PLL;
typedef complex<DB> CP;

#define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define fill(a,l,r,v) fill(a+l,a+r+1,v)
#define re(i,a,b)  for(i=(a);i<=(b);i++)
#define red(i,a,b) for(i=(a);i>=(b);i--)
#define ire(i,x) for(typedef(x.begin()) i=x.begin();i!=x.end();i++)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k))

template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;}

const DB EPS=1e-9;
inline int sgn(DB x){if(abs(x)<EPS)return 0;return(x>0)?1:-1;}
const DB Pi=acos(-1.0);

inline int gint()
  {
        int res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
    }
inline LL gll()
  {
      LL res=0;bool neg=0;char z;
        for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
        if(z==EOF)return 0;
        if(z=='-'){neg=1;z=getchar();}
        for(;z!=EOF && isdigit(z);res=res*10+z-'0',z=getchar());
        return (neg)?-res:res; 
  }

const int maxN=300000;
const LL INF=(1LL<<63)-1;

int N,M;
LL s[maxN+100];int c[maxN+100];
int f[maxN+100],a[maxN+100];
LL h[maxN+100],v[maxN+100];

int dep[maxN+100];
int to[maxN+100][20];
PLL jump[maxN+100][20];
LL minx[maxN+100][20];

int g[maxN+100],out[maxN+100];

int main()
  {
      freopen("bzoj4003.in","r",stdin);
      freopen("bzoj4003.out","w",stdout);
      int i,j;
      N=gint();M=gint();
      re(i,1,N)h[i]=gll();
      re(i,2,N)f[i]=gint(),a[i]=gint(),v[i]=gll();
      re(i,1,M)s[i]=gll(),c[i]=gint();
      
      dep[1]=1;
      re(j,0,19)to[1][j]=1;
      re(j,0,19)jump[1][j]=PLL(1,0);
      re(j,0,19)minx[1][j]=INF;
      re(i,2,N)
        {
            dep[i]=dep[f[i]]+1;
            to[i][0]=f[i];
            re(j,1,19)to[i][j]=to[to[i][j-1]][j-1];
            if(a[i]==0) jump[i][0]=PLL(1,v[i]); else jump[i][0]=PLL(v[i],0);
            re(j,1,19)
              {
                  LL da=jump[i][j-1].fi,db=jump[i][j-1].se,a=jump[to[i][j-1]][j-1].fi,b=jump[to[i][j-1]][j-1].se;
                  jump[i][j]=PLL(a*da,a*db+b);
              }
            minx[i][0]=h[i];
            re(j,1,19)
              {
                  minx[i][j]=minx[i][j-1];
                  LL a=jump[i][j-1].fi,b=jump[i][j-1].se,temp=minx[to[i][j-1]][j-1];
                  if(temp==INF) upmax(minx[i][j],INF); else upmax(minx[i][j],(temp-b-1)/a+1);
              }
        }
      
      re(i,1,M)
        {
            int p=c[i];LL x=s[i];
            red(j,19,0)
                  if(x>=minx[p][j])
                    {
                        x=x*jump[p][j].fi+jump[p][j].se;
                            p=to[p][j];
                        }
                if(x<h[p])g[p]++;
                out[i]=dep[c[i]]-dep[p];if(x>=h[p])out[i]++;
            }
        
        re(i,1,N)PF("%d\n",g[i]);
        re(i,1,M)PF("%d\n",out[i]);
        
      return 0;
  }
View Code

 

posted @ 2015-08-24 10:11  maijing  阅读(199)  评论(0编辑  收藏  举报