• 数据结构练习


    1、http://www.wikioi.com/problem/1036/

    用的是树链剖分写的LCA

     1 #include<cstring>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<vector>
     5 using namespace std;
     6 const int maxn=30000;
     7 struct xyz111
     8 {
     9     int tid,size,father,son,top,dep;
    10 }tree[maxn+50];
    11 vector<int> g[maxn+50];
    12 int n,m,label=0,q[maxn+50];
    13 void dfs(int k,int father,int dep)
    14 {
    15     tree[k]={0,1,father,0,0,dep};
    16     int maxsize=0;
    17     for(int i=0;i<g[k].size();++i)
    18         if(g[k][i]!=father)
    19         {
    20             dfs(g[k][i],k,dep+1);
    21             tree[k].size+=tree[g[k][i]].size;
    22             if(tree[g[k][i]].size>maxsize) maxsize=tree[g[k][i]].size,tree[k].son=g[k][i];
    23         }
    24 }
    25 void connect(int k,int top)
    26 {
    27     tree[k].tid=++label;
    28     tree[k].top=top;
    29     if(tree[k].son!=0) connect(tree[k].son,top);
    30     for(int i=0;i<g[k].size();++i)
    31         if(tree[k].father!=g[k][i]&&tree[k].son!=g[k][i]) connect(g[k][i],g[k][i]);
    32 }
    33 int question(int x,int y)
    34 {
    35     int a=x,b=y;
    36     while(tree[x].top!=tree[y].top)
    37     {
    38         if(tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y);
    39         x=tree[tree[x].top].father;
    40     }
    41     if(tree[x].dep>tree[y].dep) swap(x,y);
    42     return tree[a].dep+tree[b].dep-2*tree[x].dep; 
    43 }
    44 int main()
    45 {
    46     scanf("%d",&n);
    47     for(int i=1;i<=n;++i) g[i].clear();
    48     for(int i=1;i<n;++i)
    49     {
    50         int x,y;
    51         scanf("%d %d",&x,&y);
    52         g[x].push_back(y);
    53         g[y].push_back(x);
    54     }
    55     scanf("%d",&m);
    56     for(int i=1;i<=m;++i) scanf("%d",&q[i]); 
    57     dfs(1,0,0);
    58     connect(1,1);
    59     int ans=0;
    60     for(int i=2;i<=m;++i) ans+=question(q[i-1],q[i]);
    61     printf("%d",ans);
    62     return 0;
    63 }
    View Code

    2、http://www.wikioi.com/problem/1082/

    线段树的Lazy,好久没写线段树,没注意到我的存储方法线段树存储不是满的导致判断溢出的时候BUG了……

     1 #include<cstring>
     2 #include<algorithm>
     3 #include<cstdio>
     4 using namespace std;
     5 const long long maxn=200000;
     6 struct xyz111
     7 {
     8     long long l,r,add,sum;
     9 }tree[4*maxn];
    10 long long n,q,a[maxn+50];
    11 void push_down(long long k)
    12 {
    13     tree[k*2].add+=tree[k].add,tree[k*2+1].add+=tree[k].add;
    14     tree[k*2].sum+=(tree[k*2].r-tree[k*2].l+1)*tree[k].add,tree[k*2+1].sum+=(tree[k*2+1].r-tree[k*2+1].l+1)*tree[k].add;
    15     tree[k].add=0;
    16 }
    17 void build(long long k,long long l,long long r)
    18 {
    19     tree[k]={l,r,0,0};
    20     if(l==r) return;
    21     long long mid=(l+r)/2;
    22     build(k*2,l,mid);
    23     build(k*2+1,mid+1,r);
    24 }
    25 void add(long long k,long long l,long long r,long long x)
    26 {
    27     if((tree[k].l==0&&tree[k].r==0)||tree[k].l>r||tree[k].r<l) return;
    28     if(tree[k].l>=l&&tree[k].r<=r) 
    29     {
    30         tree[k].add+=x;
    31         tree[k].sum+=(tree[k].r-tree[k].l+1)*x;
    32         return;
    33     }
    34     push_down(k);
    35     add(k*2,l,r,x);
    36     add(k*2+1,l,r,x);
    37     tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
    38 }
    39 long long ask(long long k,long long l,long long r)
    40 {
    41     if((tree[k].l==0&&tree[k].r==0)||tree[k].l>r||tree[k].r<l) return 0;
    42     if(tree[k].l>=l&&tree[k].r<=r) return tree[k].sum;
    43     push_down(k);
    44     return ask(k*2,l,r)+ask(k*2+1,l,r);
    45 }
    46 int main()
    47 {
    48     scanf("%d",&n);
    49     for(int i=1;i<=4*n;++i) tree[i]={0,0,0,0};
    50     build(1,1,n);
    51     for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
    52     for(int i=1;i<=n;++i) add(1,i,i,a[i]);
    53     scanf("%d",&q);
    54     for(int i=1;i<=q;++i)
    55     {
    56         long long l,x,y,z;
    57         scanf("%lld",&l);
    58         if(l==1)
    59         {
    60             scanf("%lld %lld %lld",&x,&y,&z);
    61             add(1,x,y,z);
    62         }
    63         else 
    64         {
    65             scanf("%lld %lld",&x,&y);
    66             printf("%lld
    ",ask(1,x,y));
    67         }
    68     }
    69     return 0;
    70 }
    View Code

    3、http://www.wikioi.com/problem/1191/

    简单的线段树lazy

     1 #include<cstring>
     2 #include<algorithm>
     3 #include<cstdio>
     4 using namespace std;
     5 const int maxn=200000;
     6 struct xyz111
     7 {
     8     int l,r,v,sum;
     9 }tree[maxn*4];
    10 int n,m;
    11 void build(int k,int l,int r)
    12 {
    13     tree[k]={l,r,0,0};
    14     if(l==r) return;
    15     int mid=(l+r)/2;
    16     build(k*2,l,mid);
    17     build(k*2+1,mid+1,r);
    18 }
    19 void push_down(int k)
    20 {
    21     if(tree[k].v==0) return;
    22     tree[k*2].v=1,tree[k*2].sum=tree[k*2].r-tree[k*2].l+1;
    23     tree[k*2+1].v=1,tree[k*2+1].sum=tree[k*2+1].r-tree[k*2+1].l+1;
    24     tree[k].v=0;
    25 }
    26 void update(int k,int l,int r)
    27 {
    28     if((tree[k].l==0&&tree[k].r==0)||tree[k].l>r||tree[k].r<l) return;
    29     if(tree[k].l>=l&&tree[k].r<=r) 
    30     {
    31         tree[k].sum=tree[k].r-tree[k].l+1;
    32         tree[k].v=1;
    33         return;
    34     }
    35     push_down(k);
    36     update(k*2,l,r);
    37     update(k*2+1,l,r);
    38     tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
    39 }
    40 int ask(int k,int l,int r)
    41 {
    42     if((tree[k].l==0&&tree[k].r==0)||tree[k].l>r||tree[k].r<l) return 0;
    43     if(tree[k].l>=l&&tree[k].r<=r) return tree[k].sum;
    44     push_down(k);
    45     return ask(k*2,l,r)+ask(k*2+1,l,r);
    46 }
    47 int main()
    48 {
    49     scanf("%d %d",&n,&m);
    50     for(int i=1;i<=4*n;++i) tree[i]={0,0,0};
    51     build(1,1,n);
    52     for(int i=1;i<=m;++i)
    53     {
    54         int x,y;
    55         scanf("%d %d",&x,&y);
    56         update(1,x,y);
    57         printf("%d
    ",n-ask(1,1,n));
    58     }
    59     return 0;
    60 }
    View Code

    4、http://www.wikioi.com/problem/1299/ 

    上一题的加强版,数据范围变大了,卡线段树,正解是并查集,在模拟的基础上,将每个点的祖先定为右边的最近的没被染色的点,所以每次染色一个区间就可以很快了

     1 #include<cstring>
     2 #include<algorithm>
     3 #include<cstdio>
     4 using namespace std;
     5 const int maxn=2000000;
     6 int f[maxn+50],n,m;
     7 long long find(long long x)
     8 {
     9     if(f[x]==x) return x;
    10     return f[x]=find(f[x]);
    11 }
    12 int main()
    13 {
    14     scanf("%d %d",&n,&m);
    15     for(int i=1;i<=n;++i) f[i]=i;
    16     int ans=n;
    17     for(int i=1;i<=m;++i)
    18     {
    19         int x,y;
    20         scanf("%d %d",&x,&y);
    21         x=find(x);
    22         while(x<=y)
    23         {
    24             --ans;
    25             f[x]=x+1;
    26             x=find(x);
    27         }
    28         printf("%d
    ",ans);
    29     }
    30     return 0;
    31 }
    View Code

     5、http://www.wikioi.com/problem/1286/ 

    经典的平衡树题,这个是用Treap写的

      1 #include<cstring>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<ctime>
      5 using namespace std;
      6 const int maxn=100000,inf=1e9;
      7 struct xyz111
      8 {
      9     xyz111* ch[2];
     10     int size,value,key,num;
     11     int cmp(int x)
     12     {
     13         if(x==value) return -1;
     14         return value<x;
     15     }
     16     void maintain()
     17     {
     18         size=num;
     19         if(ch[0]!=NULL) size+=ch[0]->size;
     20         if(ch[1]!=NULL) size+=ch[1]->size;
     21     }
     22 };
     23 xyz111* root=NULL;
     24 int n,m,s=0;
     25 void rorate(xyz111* &o,int d)
     26 {
     27     xyz111* k=o->ch[d^1];
     28     o->ch[d^1]=k->ch[d];
     29     k->ch[d]=o;
     30     o->maintain();
     31     k->maintain();
     32     o=k;
     33 }
     34 void insert(xyz111* &o,int x)
     35 {
     36     if(o==NULL)
     37     {
     38         o=new xyz111();
     39         o->ch[0]=o->ch[1]=NULL;
     40         o->size=1;
     41         o->value=x;
     42         o->key=rand()%inf;
     43         o->num=1;
     44     }
     45     else
     46     {
     47         int d=o->cmp(x);
     48         if(d==-1) ++o->num;
     49         else
     50         {
     51             insert(o->ch[d],x);
     52             if(o->ch[d]->key>o->key) rorate(o,d^1);
     53         }
     54     }
     55     o->maintain();
     56 }
     57 void dfs(xyz111* &o,int x)
     58 {
     59     if(o==NULL) return;
     60     int d=o->cmp(x);
     61     if(d==0||d==-1) dfs(o->ch[0],x);
     62     if(d==1)
     63     {
     64         if(o->ch[1]!=NULL) o=o->ch[1];else o=NULL;
     65         dfs(o,x);
     66     }
     67     if(o!=NULL)o->maintain(); 
     68 }
     69 int kth(xyz111* o,int k)
     70 {
     71     int l=0;
     72     if(o->ch[0]!=NULL) l=o->ch[0]->size;
     73     if(l<k&&l+o->num>=k) return o->value;
     74     if(l+o->num<k) return kth(o->ch[1],k-l-o->num);
     75     return kth(o->ch[0],k);
     76 }
     77 int main()
     78 {
     79     srand(time(0));
     80     scanf("%d %d
    ",&n,&m);
     81     int b=0;
     82     for(int i=1;i<=n;++i)
     83     {
     84         char c;
     85         int x;
     86         scanf("%c %d
    ",&c,&x);
     87         if(c=='I') 
     88         {
     89             if(x<m) continue;
     90             insert(root,x-s);
     91             ++b;
     92         }
     93         if(c=='A') s+=x;
     94         if(c=='S')
     95         {
     96             s-=x;
     97             dfs(root,m-s);
     98         }
     99         if(c=='F') if(root==NULL||x>root->size) printf("-1
    ");else printf("%d
    ",kth(root,root->size-x+1)+s);
    100     }
    101     if(root==NULL) printf("%d",b);else printf("%d",b-root->size);
    102     return 0;
    103 }
    View Code

    6、http://www.wikioi.com/problem/1296/ 

    平衡树撸,用Treap的……

     1 #include<cstring>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<ctime>
     5 using namespace std;
     6 const int maxn=32767;
     7 struct xyz111
     8 {
     9     xyz111* ch[2];
    10     int value,key,size;
    11     int cmp(int x)
    12     {
    13         if(value==x) return -1;
    14         return value<x;
    15     }
    16     void maintain()
    17     {
    18         size=1;
    19         if(ch[0]!=NULL) size+=ch[0]->size;
    20         if(ch[1]!=NULL) size+=ch[1]->size;
    21     }
    22 };
    23 xyz111* root=NULL;
    24 int n;
    25 void rorate(xyz111* &o,int d)
    26 {
    27     xyz111* k=o->ch[d^1];
    28     o->ch[d^1]=k->ch[d];
    29     k->ch[d]=o;
    30     o->maintain();
    31     k->maintain();
    32     o=k;
    33 }
    34 void insert(xyz111* &o,int x)
    35 {
    36     if(o==NULL)
    37     {
    38         o=new xyz111();
    39         o->ch[0]=o->ch[1]=NULL;
    40         o->value=x;
    41         o->size=1;
    42         o->key=rand()%100000000;
    43     }
    44     else
    45     {
    46         int d=o->cmp(x);
    47         if(d==-1) return;
    48         insert(o->ch[d],x);
    49         if(o->ch[d]->key>o->key) rorate(o,d^1);
    50     }
    51     o->maintain();
    52 }
    53 int kth(xyz111* o,int k)
    54 {
    55     int l=0;
    56     if(o->ch[0]!=NULL) l=o->ch[0]->size;
    57     if(l+1==k) return o->value;
    58     if(l+1>k) return kth(o->ch[0],k);
    59     return kth(o->ch[1],k-l-1);
    60 }
    61 int rank(xyz111* o,int x)
    62 {
    63     if(o==NULL) return 0;
    64     int d=o->cmp(x),l=0;
    65     if(o->ch[0]!=NULL) l=o->ch[0]->size;
    66     if(d==-1) return l+1;
    67     if(d==0) return rank(o->ch[0],x);
    68     return l+1+rank(o->ch[1],x);
    69 }
    70 int main()
    71 {
    72     scanf("%d",&n);
    73     int ans;
    74     scanf("%d",&ans);
    75     insert(root,ans);
    76     for(int i=2;i<=n;++i)
    77     {
    78         int x;
    79         scanf("%d",&x);
    80         int k=rank(root,x);
    81         if(k==0) ans+=kth(root,1)-x;
    82         else
    83             if(k==root->size) ans+=x-kth(root,root->size);
    84             else
    85                 ans+=min(x-kth(root,k),kth(root,k+1)-x);
    86         insert(root,x);
    87     }
    88     printf("%d",ans);
    89     return 0;
    90 }
    View Code

    7、http://www.lydsy.com/JudgeOnline/problem.php?id=1798

    线段树成段更新,有乘法和加法 

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 const int maxn=100000;
     6 struct xyz111
     7 {
     8     int l,r;
     9     long long add,mult,sum;
    10 }tree[4*maxn+50];
    11 int n,p,m;
    12 void build(int k,int l,int r)
    13 {
    14     tree[k].l=l,tree[k].r=r,tree[k].add=0,tree[k].mult=1;
    15     if(l==r) scanf("%d",&tree[k].sum);
    16     else
    17     {
    18         int mid=(l+r)/2;
    19         build(k*2,l,mid);
    20         build(k*2+1,mid+1,r);
    21         tree[k].sum=tree[k*2].sum+tree[k*2+1].sum;
    22     }
    23 }
    24 void maintain(int k,long long add,long long mult)
    25 {
    26     if(tree[k].l==0&&tree[k].r==0) return;
    27     tree[k].mult=(tree[k].mult*mult)%p;
    28     tree[k].add=((tree[k].add*mult)%p+add)%p;
    29     tree[k].sum=((tree[k].sum+(tree[k].sum*(mult-1))%p)%p+(add*(tree[k].r-tree[k].l+1))%p)%p;
    30 }
    31 void updata(int k,int l,int r,long long add,long long mult)
    32 {
    33     if(tree[k].l>r||tree[k].r<l||(tree[k].l==0&&tree[k].r==0)) return;
    34     if(tree[k].l>=l&&tree[k].r<=r) maintain(k,add,mult);
    35     else
    36     {
    37         int mid=(tree[k].l+tree[k].r)/2;
    38         maintain(k*2,tree[k].add,tree[k].mult);
    39         maintain(k*2+1,tree[k].add,tree[k].mult);
    40         tree[k].mult=1,tree[k].add=0;
    41         updata(k*2,l,r,add,mult);
    42         updata(k*2+1,l,r,add,mult);
    43         tree[k].sum=(tree[k*2].sum+tree[k*2+1].sum)%p;
    44     }
    45 }
    46 int ask(int k,int l,int r)
    47 {
    48     if(tree[k].l>r||tree[k].r<l||(tree[k].l==0&&tree[k].r==0)) return 0;
    49     if(tree[k].l>=l&&tree[k].r<=r) return tree[k].sum;
    50     int mid=(tree[k].l+tree[k].r)/2;
    51     maintain(k*2,tree[k].add,tree[k].mult);
    52     maintain(k*2+1,tree[k].add,tree[k].mult);
    53     tree[k].mult=1,tree[k].add=0;
    54     return (ask(k*2,l,r)+ask(k*2+1,l,r))%p;
    55 }
    56 int main()
    57 {
    58     scanf("%d %d",&n,&p);
    59     for(int k=1;k<=4*n;++k)    tree[k].l=tree[k].r=0,tree[k].add=0,tree[k].mult=1,tree[k].sum=0;
    60     build(1,1,n);
    61     int k=1;
    62     scanf("%d",&m);
    63     for(int i=1;i<=m;++i)
    64     {
    65         int a,b,c,d;
    66         scanf("%d",&a);
    67         if(a==3) 
    68         {
    69             scanf("%d %d",&b,&c);
    70             printf("%d
    ",ask(1,b,c));
    71             continue;
    72         }
    73         scanf("%d %d %d",&b,&c,&d);
    74         if(a==1) updata(1,b,c,0,d);else updata(1,b,c,d,1); 
    75     }
    76     k=1;
    77     return 0;
    78 }
    View Code

     8、http://codevs.cn/problem/3303/

    splay维护数列的简单问题

     1 #include<cstring>
     2 #include<algorithm>
     3 #include<cstdio>
     4 using namespace std;
     5 const int maxn=100000;
     6 int pre[maxn+50],ch[maxn+50][2],flip[maxn+50],key[maxn+50],size[maxn+50];
     7 int n,m,root=0,len=0;
     8 void update(int k)
     9 {
    10     size[k]=size[ch[k][0]]+size[ch[k][1]]+1;
    11 }
    12 void pushdown(int k)
    13 {
    14     if(flip[k]==0) return;
    15     flip[k]=0;
    16     swap(ch[k][0],ch[k][1]);
    17     flip[ch[k][0]]^=1;
    18     flip[ch[k][1]]^=1;
    19 }
    20 void rorate(int k,int d)
    21 {
    22     int f=pre[pre[k]],p=pre[k];
    23     pushdown(p),pushdown(k);
    24     ch[p][d^1]=ch[k][d];
    25     pre[ch[k][d]]=p;
    26     ch[k][d]=p;
    27     pre[k]=f;
    28     pre[p]=k;
    29     if(f) ch[f][ch[f][1]==p]=k;else root=k;
    30     update(p),update(k);
    31 }
    32 void splay(int x,int goal)
    33 {
    34     while(pre[x]!=goal)
    35     {
    36         pushdown(x);
    37         if(pre[pre[x]]==goal) rorate(x,ch[pre[x]][0]==x);
    38         else
    39         {
    40             int d1=ch[pre[x]][0]==x,d2=ch[pre[pre[x]]][0]==pre[x];
    41             if(d1==d2) rorate(pre[x],d2),rorate(x,d1);
    42             else rorate(x,d1),rorate(x,d2);
    43         }
    44     }
    45     update(x);
    46     if(goal==0) root=x;
    47 }
    48 void insert(int v)
    49 {
    50     int k=root;
    51     while(ch[k][1]!=0) k=ch[k][1];
    52     ++len;
    53     pre[len]=k,ch[len][0]=ch[len][1]=0,flip[len]=0,key[len]=v,size[len]=1,ch[k][1]=len;
    54     if(root==0) root=k;
    55     splay(len,0);
    56 }
    57 void find(int k,int goal)
    58 {
    59     int t=root;
    60     while(true)
    61     {
    62         pushdown(t);
    63         if(size[ch[t][0]]+1==k) break;
    64         if(k<=size[ch[t][0]]) t=ch[t][0];else k-=size[ch[t][0]]+1,t=ch[t][1];
    65     }
    66     splay(t,goal);
    67 }
    68 void ask(int k)
    69 {
    70     if(k==0) return;
    71     pushdown(k);
    72     ask(ch[k][0]);
    73     if(key[k]>=2&&key[k]<=n+1)printf("%d ",key[k]-1);
    74     ask(ch[k][1]);
    75 }
    76 int main()
    77 {
    78     scanf("%d %d",&n,&m);
    79     for(int i=1;i<=n+2;++i)  insert(i);
    80     splay((n+2)/2,0);
    81     for(int i=1;i<=m;++i)
    82     {
    83         int x,y;
    84         scanf("%d %d",&x,&y);
    85         x+=1,y+=1;
    86         find(x-1,0);
    87         find(y+1,root);
    88         flip[ch[ch[root][1]][0]]^=1;
    89     }
    90     ask(root);
    91     return 0;
    92 }
    View Code

     9、http://www.lydsy.com:808/JudgeOnline/problem.php?id=2002

    link-cut tree模板

      1 #include<cstring>
      2 #include<algorithm>
      3 #include<vector>
      4 #include<cstdio>
      5 using namespace std;
      6 const int maxn=200000;
      7 bool root[maxn+50];//root[i]表示节点i是否为它所在辅助树的根
      8 int father[maxn+50],size[maxn+50],ch[maxn+50][2];
      9 //father[i]记录i的父亲,他的父亲可能跟i在一个辅助树上也可能不在;size[i]表示在i所在的辅助树中以i为子树的节点个数;ch[i][0..1]记录的是i在辅助树中的左儿子和右儿子,如果没有用0表示
     10 int n,m;
     11 void update(int k)
     12 {
     13     if(k==0) return;
     14     size[k]=size[ch[k][0]]+size[ch[k][1]]+1;
     15 }
     16 void rorate(int k,int d)
     17 {
     18     int p=father[k],f=father[father[k]];
     19     ch[p][d^1]=ch[k][d];
     20     father[ch[k][d]]=p;
     21     ch[k][d]=p;
     22     father[p]=k;
     23     father[k]=f;
     24     if(f) 
     25         if(ch[f][0]==p) ch[f][0]=k;else if(ch[f][1]==p) ch[f][1]=k;//此处一定要注意,因为可能f和k不在一个辅助树上
     26     update(p);
     27     update(k);
     28     if(root[p]) root[k]=1,root[p]=0;//root[p]=0一定要记得加上
     29 }
     30 void splay(int k)
     31 {
     32     while (!root[k])
     33     {
     34         if(root[father[k]]) rorate(k,ch[father[k]][0]==k);
     35         else
     36         {
     37             int d1=ch[father[k]][0]==k,d2=ch[father[father[k]]][0]==father[k];
     38             if(d1==d2) rorate(father[k],d2),rorate(k,d1);else rorate(k,d1),rorate(k,d2);
     39         }
     40     }
     41     update(k);
     42 }
     43 void access(int x)
     44 {
     45     splay(x);
     46     while(father[x])
     47     {
     48         int y=father[x];
     49         splay(y);
     50         root[ch[y][1]]=1;
     51         root[x]=0;
     52         ch[y][1]=x;
     53         update(y);
     54         splay(x);
     55     }
     56 }
     57 void cut(int x)
     58 {
     59     access(x);
     60     splay(x);
     61     father[ch[x][0]]=0;
     62     root[ch[x][0]]=1;
     63     ch[x][0]=0;
     64     update(x);
     65 }
     66 void link(int x,int y)
     67 {
     68     if(y>n) y=n+1;
     69     father[x]=y;
     70 }
     71 int main()
     72 {
     73     freopen("ce.in","r",stdin);
     74     freopen("ce.out","w",stdout);
     75     scanf("%d",&n);
     76     for(int i=1;i<=n;++i) 
     77     {
     78         scanf("%d",&father[i]);
     79         father[i]+=i;
     80         if(father[i]>n) father[i]=n+1;
     81     }
     82     scanf("%d",&m);
     83     memset(size,0,sizeof(size));
     84     for(int i=1;i<=n+1;++i) size[i]=1;
     85     memset(root,1,sizeof(root));
     86     memset(ch,0,sizeof(ch));
     87     for(int i=1;i<=m;++i)
     88     {
     89         int x,y,z;
     90         scanf("%d %d",&x,&y);
     91         ++y;
     92         if(x==1)
     93         {
     94             access(y);
     95             printf("%d
    ",size[ch[y][0]]);
     96         }
     97         else
     98         {
     99             scanf("%d",&z);
    100             cut(y);
    101             link(y,y+z);
    102         }
    103     }
    104     return 0;
    105 }
    106             
    View Code

    10、还是上一题

    分块模板 

     1 #include<cstring>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<vector>
     5 #include<cmath>
     6 using namespace std;
     7 const int maxn=200000;
     8 int k[maxn+50],block[maxn+50],next[maxn+50],step[maxn+50];
     9 int n,m,l;
    10 //block[i]计数i所处的块的编号;next[i]表示i一直往后跳直到跳出当前块的位置;step[i]表示i到next[i]要跳几步
    11 void build(int l,int r)
    12 {
    13     for(int i=r;i>=l;--i)
    14         if(i+k[i]>n) next[i]=0,step[i]=1;
    15         else
    16             if(block[i]==block[i+k[i]]) next[i]=next[i+k[i]],step[i]=step[i+k[i]]+1;
    17             else next[i]=i+k[i],step[i]=1;
    18 }//build(l,r)表示把[l,r]这一段重新维护一下
    19 void ask(int x)
    20 {
    21     int s=0;
    22     while(x)
    23     {
    24         s+=step[x];
    25         x=next[x];
    26     }
    27     printf("%d
    ",s);
    28 }
    29 int main()
    30 {
    31     freopen("ce.in","r",stdin);
    32     freopen("ce.out","w",stdout);
    33     scanf("%d",&n);
    34     l=int(sqrt(n));
    35     for(int i=1;i<=n;++i) scanf("%d",&k[i]),block[i]=(i-1)/l+1;
    36     build(1,n);
    37     scanf("%d",&m);
    38     for(int i=1;i<=m;++i)
    39     {
    40         int x,y,z;
    41         scanf("%d %d",&x,&y);
    42         ++y;
    43         if(x==1) ask(y);else scanf("%d",&z),k[y]=z,build(l*(block[y]-1)+1,y);
    44     }
    45     return 0;
    46 }
    View Code

     11、http://www.lydsy.com:808/JudgeOnline/problem.php?id=1036

    树链剖分模板

      1 #include<cstring>
      2 #include<algorithm>
      3 #include<cstdio>
      4 #include<vector>
      5 using namespace std;
      6 const int maxn=30000,inf=1e9;
      7 struct wjmzbmr
      8 {
      9     int tid,top,size,son,dep,father,v;
     10 }tree[maxn+50];
     11 struct fotile96
     12 {
     13     int maxnum,sum;
     14 }f[4*maxn+50];
     15 vector<int> g[maxn+50];
     16 int pos[maxn+50];
     17 int n,label=0,q;
     18 void dfs(int x,int fa,int dep)
     19 {
     20     tree[x]=(wjmzbmr){0,0,1,0,dep,fa,tree[x].v};
     21     int m=0;
     22     for(int i=0;i<g[x].size();++i)
     23         if(g[x][i]!=fa)
     24         {
     25             dfs(g[x][i],x,dep+1);
     26             tree[x].size+=tree[g[x][i]].size;
     27             if(tree[g[x][i]].size>m) m=tree[g[x][i]].size,tree[x].son=g[x][i];
     28         }
     29 }
     30 void connect(int x,int top)
     31 {
     32     tree[x].tid=++label,pos[tree[x].tid]=x;
     33     tree[x].top=top;
     34     if(tree[x].son!=0) connect(tree[x].son,top);
     35     for(int i=0;i<g[x].size();++i)
     36         if(g[x][i]!=tree[x].father&&g[x][i]!=tree[x].son) connect(g[x][i],g[x][i]);
     37 }
     38 void make(int k,int l,int r)
     39 {
     40     if(l>r) return;
     41     if(l==r) f[k].maxnum=f[k].sum=tree[pos[l]].v;
     42     else
     43     {
     44         int mid=(l+r)>>1;
     45         make(k*2,l,mid);
     46         make(k*2+1,mid+1,r);
     47     f[k].sum=f[k*2].sum+f[k*2+1].sum;
     48     f[k].maxnum=max(f[k*2].maxnum,f[k*2+1].maxnum);
     49     }
     50 }
     51 void change(int k,int l,int r,int x,int y)
     52 {
     53     if(l>r||r<x||l>x) return;
     54     if(l==r)
     55     {
     56         if(l==x) f[k].maxnum=y,f[k].sum=y;
     57         return;
     58     }
     59     int mid=(l+r)>>1;
     60     change(k*2,l,mid,x,y);
     61     change(k*2+1,mid+1,r,x,y);
     62     f[k].sum=f[k*2].sum+f[k*2+1].sum;
     63     f[k].maxnum=max(f[k*2].maxnum,f[k*2+1].maxnum);
     64 }
     65 int qqmax(int k,int l,int r,int ll,int rr)
     66 {
     67     if(l>r||l>rr||r<ll) return -inf;
     68     if(l>=ll&&r<=rr) return f[k].maxnum;
     69     int mid=(l+r)>>1;
     70     return max(qqmax(k*2,l,mid,ll,rr),qqmax(k*2+1,mid+1,r,ll,rr));
     71 }
     72 int qmax(int x,int y)
     73 {
     74     int ans=-inf;
     75     while(tree[x].top!=tree[y].top)
     76     {
     77         if(tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y);
     78         ans=max(ans,qqmax(1,1,n,tree[tree[x].top].tid,tree[x].tid));
     79         x=tree[tree[x].top].father;
     80     }
     81     if(tree[x].dep>tree[y].dep) swap(x,y);
     82     ans=max(ans,qqmax(1,1,n,tree[x].tid,tree[y].tid));
     83     return ans;
     84 }
     85 int qqsum(int k,int l,int r,int ll,int rr)
     86 {
     87     if(l>r||l>rr||r<ll) return 0;
     88     if(l>=ll&&r<=rr) return f[k].sum;
     89     int mid=(l+r)>>1;
     90     return qqsum(k*2,l,mid,ll,rr)+qqsum(k*2+1,mid+1,r,ll,rr);
     91 }
     92 int qsum(int x,int y)
     93 {
     94     int ans=0;
     95     while(tree[x].top!=tree[y].top)
     96     {
     97         if(tree[tree[x].top].dep<tree[tree[y].top].dep) swap(x,y);
     98         ans+=qqsum(1,1,n,tree[tree[x].top].tid,tree[x].tid);
     99         x=tree[tree[x].top].father;
    100     }
    101     if(tree[x].dep>tree[y].dep) swap(x,y);
    102     ans+=qqsum(1,1,n,tree[x].tid,tree[y].tid);
    103     return ans;
    104 }
    105 int main()
    106 {
    107     freopen("ce.in","r",stdin);
    108     freopen("ce.out","w",stdout);
    109     scanf("%d",&n);
    110     for(int i=1;i<=n;++i) g[i].clear();
    111     for(int i=1;i<n;++i) 
    112     {
    113         int x,y;
    114         scanf("%d %d",&x,&y);
    115         g[x].push_back(y);
    116         g[y].push_back(x);
    117     }
    118     for(int i=1;i<=n;++i) scanf("%d",&tree[i].v);
    119     dfs(1,0,0);
    120     connect(1,1);
    121     make(1,1,n);
    122     scanf("%d
    ",&q);
    123     for(int i=1;i<=q;++i)
    124     {
    125         int x,y;
    126         char s[10];
    127         scanf("%s %d %d
    ",s,&x,&y);
    128         if(s[0]=='C') change(1,1,n,tree[x].tid,y);
    129         if(s[1]=='M') printf("%d
    ",qmax(x,y));
    130         if(s[1]=='S') printf("%d
    ",qsum(x,y));
    131     }
    132     return 0;
    133 }
    View Code

     12、SAP模版

     1 #include<cstring>
     2 #include<algorithm>
     3 #include<cstdio>
     4 #include<vector>
     5 using namespace std;
     6 const int maxn=20000,inf=1e8;
     7 struct wjmzbmr
     8 {
     9     int from,to,flow;
    10 }E[maxn+50];
    11 vector<int> g[maxn+50];
    12 int n,m,len=-1;
    13 int d[maxn+50,dv[maxn+50];
    14 int dfs(int k,int flow)
    15 {
    16     if(k==n) return flow;
    17     int f=0;
    18     for(int i=0;i<g[k].size();++i)
    19     {
    20         wjmzbmr e=E[g[k][i]];
    21         int k=dfs(e.to,min(flow-f,e.flow));
    22         e.flow-=k;
    23         E[g[k][i]^1].flow+=k;
    24         f+=k;
    25         if(f==flow) return f;
    26     }
    27     if(d[1]==n) return f;
    28     --dv[d[k]];
    29     if(dv[d[k]]==0) d[1]=n;
    30     ++d[k];
    31     ++dv[d[k]];
    32 }
    33 int main()
    34 {
    35     freopen("ce.in","r",stdin);
    36     scanf("%d %d",&n,&m);
    37     for(int i=1;i<=m;++i)
    38     {
    39         int a,b,c;
    40         scanf("%d %d %d",&a,&b,&c);
    41         ++len;
    42         e[len]=(wjmzbmr){a,b,c};
    43         g[a].push_back(len);
    44         ++len;
    45         e[len]=(wjmzbmr){b,a,0};
    46         g[b].push_back(len);
    47     }
    48     for(int i=1;i<=n;++i) d[i]=n;
    49     memset(dv,0,sizeof(dv));
    50     dv[1]=n;
    51     int ans=0;
    52     while (d[1]<n)
    53     {
    54         ans+=dfs(1,inf);
    55     }
    56     return 0;
    57 }
    View Code

    (未完待续)

  • 相关阅读:
    highcharts绘制股票k线
    利用meta标签将http请求换成https请求
    path.join 与 path.resolve 的区别
    【转】弧度和角度的转换
    块级元素和行内元素的区别 (block vs. inline)
    ubuntu下安装Apache + PHP + Mysql
    [读书笔记] CSS权威指南2: 结构和层叠
    [读书笔记] CSS权威指南1: 选择器
    [读书笔记] Head First 设计模式
    深入浅出React Native 3: 从零开始写一个Hello World
  • 原文地址:https://www.cnblogs.com/wmrv587/p/3859421.html
Copyright © 2020-2023  润新知