NOI2015

D1T1

并查集。

#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<int,int> PII;

typedef complex<DB> CP;



#define mmst(a,v) memset(a,v,sizeof(a))

#define mmcy(a,b) memcpy(a,b,sizeof(a))

#define re(i,a,b)  for(i=a;i<=b;i++)

#define red(i,a,b) for(i=a;i>=b;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=100000;

const int maxcnt=2*maxN;



int N;

struct Ta{int e,x,y;}a[maxN+100];

int cnt,bak[maxcnt+100];



int pa[maxcnt+100];

inline int findroot(int a){return pa[a]<0?a:pa[a]=findroot(pa[a]);}

inline void BCJ_Union(int a,int b)

  {

      int f1=findroot(a),f2=findroot(b);

      if(f1==f2)return;

      if(pa[f1]>pa[f2])swap(f1,f2);

      pa[f1]=pa[f1]+pa[f2];

      pa[f2]=f1;

  }



int main()

  {

      freopen("prog.in","r",stdin);

      freopen("prog.out","w",stdout);

      int i;

      for(int Case=gint();Case;Case--)

        {

            N=gint();

            re(i,1,N){a[i].x=gint();a[i].y=gint();a[i].e=gint();}

            cnt=0;

            re(i,1,N){bak[++cnt]=a[i].x;bak[++cnt]=a[i].y;}

            sort(bak+1,bak+cnt+1);

            cnt=unique(bak+1,bak+cnt+1)-bak-1;

            re(i,1,N){a[i].x=lower_bound(bak+1,bak+cnt+1,a[i].x)-bak;a[i].y=lower_bound(bak+1,bak+cnt+1,a[i].y)-bak;}

            re(i,1,cnt)pa[i]=-1;

            re(i,1,N)if(a[i].e==1)BCJ_Union(a[i].x,a[i].y);

            int flag=1;

            re(i,1,N)if(a[i].e==0 && findroot(a[i].x)==findroot(a[i].y)){flag=0;break;}

            if(flag)PF("YES\n");else PF("NO\n");

        }

      return 0;

  }
View Code

D1T2

树链剖分+线段树。

树链剖分中,我们在求边的编号的时候,我们可以用DFS,虽然这样麻烦一点,但是可以保证同一棵子树的编号在线段树中是连续的。

但考试的时候并没有想到这一点。

然后用了LCT,打了8KB,我都不想说话了。

#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<int,int> PII;

typedef complex<DB> CP;



#define mmst(a,v) memset(a,v,sizeof(a))

#define mmcy(a,b) memcpy(a,b,sizeof(a))

#define re(i,a,b)  for(i=a;i<=b;i++)

#define red(i,a,b) for(i=a;i>=b;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=100000;

const int maxQ=100000;



struct Tnode

  {

      Tnode *fa,*son[2],*path_parent;

      int R,L,val,add;

      inline Tnode(){fa=son[0]=son[1]=path_parent=0;R=L=val=add=0;}

      inline void down()

        {

            if(add!=0)

              {

                  if(son[0]){son[0]->val+=add;son[0]->add+=add;}

                  if(son[1]){son[1]->val+=add;son[1]->add+=add;}

                  add=0;

              }

        }

  };



int N,Q;

int fa[maxN+100];

int now,first[maxN+100];

struct Tedge{int v,next;}edge[maxN+100];

int dep[maxN+100];

int jump[maxN+100][31];

Tnode *pos[maxN+100];



inline void addedge(int u,int v)

  {

      now++;

      edge[now].v=v;

      edge[now].next=first[u];

      first[u]=now;

  }



int head,tail,que[maxN+100];

int size[maxN+100],heavy[maxN+100],top[maxN+100],w[maxN+100],cnt;

inline void BFS()

  {

      int i,j,u,v;

      dep[que[head=tail=1]=1]=1;

      while(head<=tail)

        {

            u=que[head++];

            for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)dep[que[++tail]=v]=dep[u]+1;

        }

      re(i,1,tail)

        {

            u=que[i];

            jump[u][0]=fa[u];

            re(j,1,30)jump[u][j]=jump[jump[u][j-1]][j-1];

        }

      red(j,tail,1)

        {

            u=que[j];

            size[u]=1;

            heavy[u]=-1;

            for(i=first[u],v=edge[i].v;i!=-1;i=edge[i].next,v=edge[i].v)

              {

                  size[u]+=size[v];

                  if(heavy[u]==-1 || size[v]>size[heavy[u]])heavy[u]=v;

              }

        }

      top[1]=1;

      re(i,2,tail)

        {

              u=que[i];

            if(heavy[fa[u]]==u) top[u]=top[fa[u]]; else top[u]=u;

        }

      mmst(w,-1);

      cnt=0;

      re(i,1,tail)

        {

            u=que[i];

            if(w[u]!=-1)continue;

            int r=u;

            while(r!=-1){w[r]=++cnt;r=heavy[r];}

        }

  };



int tree[4*maxN+100];

inline void down(int root)

  {

      if(tree[root]!=0)

        {

            tree[root*2]=tree[root*2+1]=tree[root];

            tree[root]=0;

        }

  }

inline void update(int root,int l,int r,int x,int y,int val)

  {

      if(l>r || x>y || r<x || y<l) return;

      if(x<=l && r<=y){tree[root]=val;return;}

      down(root);

      int mid=(l+r)/2;

      update(root*2,l,mid,x,y,val);

      update(root*2+1,mid+1,r,x,y,val);

  }

inline int ask(int root,int l,int r,int x)

  {

      if(l<=x && x<=r && tree[root]!=0) return tree[root];

      if(x<=l && r<=x) return tree[root];

      down(root);

      int mid=(l+r)/2;

      if(x<=mid) return ask(root*2,l,mid,x); else return ask(root*2+1,mid+1,r,x);

  }

inline void Cover(int a,int b,int val)

  {

      int f1=top[a],f2=top[b];

      while(f1!=f2)

        {

            if(dep[f1]<dep[f2]){swap(f1,f2);swap(a,b);}

            update(1,1,cnt,w[f1],w[a],val);

            a=fa[f1];

            f1=top[a];

        }

      if(dep[a]>dep[b])swap(a,b);

      update(1,1,cnt,w[a],w[b],val);

  }

inline Tnode *findp(int x)

  {

      if(x==0) return pos[0];

      x=ask(1,1,cnt,w[x]);

      return (x==0)?0:pos[x];

  }



inline void Splay_Rotate(Tnode *x,int flag)

  {

      Tnode *y=x->fa,*z=y->fa;

      y->son[flag^1]=x->son[flag];if(x->son[flag])x->son[flag]->fa=y;

      x->son[flag]=y;y->fa=x;

      x->path_parent=y->path_parent;y->path_parent=0;

      x->fa=z;if(z)z->son[(y==z->son[1])]=x;

  }

inline void Splay(Tnode *x)

  {

      Tnode *y,*z;

      while(x->fa)

        {

            y=x->fa;z=y->fa;

            if(z)z->down();y->down();x->down();

            if(!z){Splay_Rotate(x,x==y->son[0]);return;}

            int L=(x==y->son[0]),R=(y==z->son[0]);

            if(L==R){Splay_Rotate(y,L);Splay_Rotate(x,R);continue;}

            if(L!=R){Splay_Rotate(x,L);Splay_Rotate(x,R);continue;}

        }

      x->down();

  }

inline void LCT_Access(Tnode *x)

  {

      Tnode *y;

      for(y=0;x;y=x,x=x->path_parent)

        {

            Splay(x);

            if(x->son[1]){x->son[1]->fa=0;x->son[1]->path_parent=x;}

            x->son[1]=y;

            if(y){y->fa=x;y->path_parent=0;}

        }

  }

inline void LCT_update(Tnode *x,int v)

  {

      LCT_Access(x);

      Splay(x);

      x->val+=v;

      x->add+=v;

      x->down();

  }

inline void LCT_Delete(Tnode *u,Tnode *v)

  {

      LCT_Access(u);

      LCT_Access(v);

      u->path_parent=0;

  }

inline int swim(int x,int H)

  {

      int res=x;

      for(int i=0;H!=0;H/=2,i++)if(H&1)res=jump[res][i];

      return res;

  }

inline void LCT_Fen(Tnode *x,int ca)

  {

      int R,L,G;

      Tnode *p;

      if(ca==x->R)return;

      R=x->R;

      L=x->L;

      G=swim(R,dep[R]-dep[ca]-1);

      p=findp(fa[L]);

      LCT_Delete(x,p);

      pos[ca]=new Tnode;

      pos[ca]->path_parent=p;

      pos[ca]->R=ca;

        pos[ca]->L=L;

      pos[ca]->val=x->val;

      Cover(ca,L,ca);

      x->path_parent=pos[ca];

      x->L=G;

      x->val-=dep[ca]-dep[L]+1;

  }



inline int isblack(int x)

  {

      Tnode *p=findp(x);

      if(!p)return 0;

      LCT_Access(p);

      Splay(p);

      Tnode *t=p;t->down();

      while(t->son[0]){t=t->son[0];t->down();}

      return t==pos[0];

  }



inline int findL(int x)

  {

      int i;

      red(i,30,0)if(jump[x][i]!=0 && !isblack(jump[x][i])) x=jump[x][i];

      return x;

  }



int main()

  {

      freopen("manager.in","r",stdin);

      freopen("manager.out","w",stdout);

      int i;

      N=gint();

      now=-1;mmst(first,-1);

      re(i,2,N)

          {

              fa[i]=gint()+1;

              addedge(fa[i],i);

            }

      BFS();

      pos[0]=new Tnode;

      Q=gint();

      while(Q--)

        {

            char s[20];int x,ca,R,L;

            Tnode *p;

            SF("%s%d\n",s,&x);x++;

            switch(s[0])

              {

                  case 'i':

                      if(isblack(x)){PF("0\n");continue;}

                      L=findL(x);

                      ca=fa[L];

                      p=findp(ca);

                      LCT_Fen(p,ca);

                      pos[x]=new Tnode;

                      pos[x]->R=x;pos[x]->L=L;

                      Cover(x,L,x);

                      pos[x]->path_parent=findp(ca);

                      LCT_update(pos[x],dep[x]-dep[ca]);

                      PF("%d\n",dep[x]-dep[ca]);

                  break;

                  case 'u':

                      if(!isblack(x)){PF("0\n");continue;}

                      p=findp(x);

                      R=p->R;

                            L=p->L;

                            ca=fa[L];

                      PF("%d\n",p->val-(dep[x]-dep[L]));

                      LCT_update(p,-p->val);

                            LCT_Delete(p,findp(ca));

                            //////////

                            if(x==L)continue;

                            x=fa[x];

                            pos[x]=new Tnode;

                      pos[x]->R=x;pos[x]->L=L;

                      Cover(x,L,x);

                      pos[x]->path_parent=findp(ca);

                      LCT_update(pos[x],dep[x]-dep[ca]);

                  break;

              }

        }

      return 0;

  }
View Code

D1T3

背包+状压DP。

神题。。。。。。

ppt讲得比较清晰了。

30%的做法:

集合A和集合B互质就是没有包含相同的质因数,我们将每个数分解质因数。

分解质因数求出每个数包含哪些质因子,使用二进制状态压缩,存在s[i]里,每个数看作一个物品,做一次二进制状态的背包DP。

容易得到g[j|s[i]]=(g[j|s[i]]+g[j])%Mod

这是一个背包,所以j倒序循环。

100%的做法:

注意到小于等于sqrt(N)的质因数最多只有9个,每一个数最多包含一个大于sqrt(N)的质因数。

s[i]就表示i在2...sqrt(N)中包含哪些质因子,使用二进制状态压缩。

f(i)[x][y]表示可以使用前i个大质数和全部小质数,A集合包含的小质数的状态为x(二进制),B集合包含的小质数的状态为y(二进制)时的方案数。

容易得到初值f(0)[x][y]=g[x]*g[y]%Mod,其中x&y==0。

其中i这一维可以在背包中忽略。

转移时,枚举包含第i个大质数的所有整数z,他们可以某些且至少一个分配在A集合,可以某些且至少一个分配在B集合,也可以全部丢弃不用。单是绝对不可以某些分配在A集合,某些分配在B集合。

我们在做第i个大质数的时候,记d[x][y][0]表示A集合包含的小质数的状态为x(二进制),B集合包含的小质数的状态为y(二进制),包含第i个大质数的所有至少一个整数z都分配在A集合中的方案数。

同理,d[x][y][0]表示A集合包含的小质数的状态为x(二进制),B集合包含的小质数的状态为y(二进制),包含第i个大质数的某些且至少一个整数z都分配在B集合中的方案数。

分给A:d[x|s[z]][y][0]=(d[x|s[z]][y][0]+d[x][y][0]+f[x][y])%Mod

分给B:d[x][y|s[z]][1]=(d[x][y|s[z]][1]+d[x][y][0]+f[x][y])%Mod

这是一个背包,所以x和y倒序循环。

至于为什么还要加上一个f[x][y],因为d[x][y][0]是前面用了至少一个整数z,但是有可能前面没有用整数z,用了当前的整数z,所以要加f[x][y]。

累加:f[x][y]=(f[x][y]+d[x][y][0]+d[x][y][1])%Mod

#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<int,int> PII;

typedef complex<DB> CP;



#define mmst(a,v) memset(a,v,sizeof(a))

#define mmcy(a,b) memcpy(a,b,sizeof(a))

#define re(i,a,b)  for(i=a;i<=b;i++)

#define red(i,a,b) for(i=a;i>=b;i--)

#define fi first

#define se second

#define m_p(a,b) make_pair(a,b)

#define SF scanf

#define PF printf



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=500;



int N;

LL Mod;

int flag[maxN+100];

int cnt,ge,prime[maxN+100];

int s[maxN+100];

LL g[(1<<10)+100];

LL f[(1<<9)+10][(1<<9)+10],d[(1<<9)+10][(1<<9)+10][2];

LL ans;



#define wei(v,k) (((v)>>((k)-1))&1)

#define two(k) (1<<(k-1))



int main()

  {

      freopen("dinner.in","r",stdin);

      freopen("dinner.out","w",stdout);

      int i,j,k;

      N=gint();Mod=gll();

      re(i,2,N)

        {

            if(!flag[i])prime[++cnt]=i;

            for(j=1;j<=cnt && prime[j]*i<=N;j++)

              {

                  flag[i*prime[j]]=1;

                  if(i%prime[j]==0)break;

              }

        }

      if(cnt<=10)

        {

              re(i,2,N)re(j,1,cnt)if(i%prime[j]==0)s[i]|=two(j);

              g[0]=1;

              re(i,2,N)red(j,(1<<cnt)-1,0)g[j|s[i]]=(g[j|s[i]]+g[j])%Mod;

              ans=0;

              re(i,0,(1<<cnt)-1)re(j,0,(1<<cnt)-1)if((i&j)==0)ans=(ans+g[i]*g[j])%Mod;

              cout<<ans<<endl;

        }

      else

        {

            ge=9;

            re(i,2,N)re(j,1,ge)if(i%prime[j]==0)s[i]|=two(j);

            g[0]=1;

            re(i,2,N)

              {

                  int t=i;

                  re(j,1,ge)while(t%prime[j]==0)t/=prime[j];

                  if(t!=1)continue;

                  red(j,(1<<ge)-1,0)g[j|s[i]]=(g[j|s[i]]+g[j])%Mod;

              }

            re(i,0,(1<<ge)-1)re(j,0,(1<<ge)-1)if((i&j)==0)f[i][j]=g[i]*g[j]%Mod;

            re(k,ge+1,cnt)

              {

                  mmst(d,0);

                for(int v=prime[k];v<=N;v+=prime[k])

                  red(i,(1<<ge)-1,0)red(j,(1<<ge)-1,0)if((i&j)==0)

                    {

                        if(((i|s[v])&j)==0)d[i|s[v]][j][0]=(d[i|s[v]][j][0]+d[i][j][0]+f[i][j])%Mod;

                        if((i&(j|s[v]))==0)d[i][j|s[v]][1]=(d[i][j|s[v]][1]+d[i][j][1]+f[i][j])%Mod;

                    }

                re(i,0,(1<<ge)-1)re(j,0,(1<<ge)-1)if((i&j)==0)f[i][j]=(f[i][j]+d[i][j][0]+d[i][j][1])%Mod;

              }

            ans=0;

            re(i,0,(1<<ge)-1)re(j,0,(1<<ge)-1)if((i&j)==0)ans=(ans+f[i][j])%Mod;

            cout<<ans<<endl;

        }

      return 0;

  }
View Code

 

你可能感兴趣的:(NOI2015)