算法总结数据结构

Posted zsnuo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法总结数据结构相关的知识,希望对你有一定的参考价值。

【splay】

〖模板代码

技术分享图片
 1 void rotate(int x,int& k)
 2 {
 3     int y=fa[x],z=fa[y],l,r;
 4     l=(tr[y][1]==x);r=l^1;
 5     if(y==k)k=x;
 6     else tr[z][tr[z][1]==y]=x;
 7     fa[x]=z;fa[y]=x;fa[tr[x][r]]=y;
 8     tr[y][l]=tr[x][r];tr[x][r]=y;
 9     update(y);update(x);
10 }
11 void splay(int x,int &k)
12 {
13     while(x!=k)
14     {
15         int y=fa[x],z=fa[y];
16         if(y!=k)
17         {
18             if(c[y][0]==x^c[z][0]==y)rotate(x,k);
19             else rotate(y,k);
20         }
21         rotate(x,k);
22     }
23 }
View Code

〖相关题目

1.【bzoj3786】星系探索

题意:见原题

分析:Zsnuoの博客

技术分享图片
  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 using namespace std;
  5 const int inf=0x3f3f3f3f;
  6 const int N=100010;
  7 struct node{int ch[2],size,fa,t,num;long long v,sum,tag;}tr[N<<1];
  8 struct edge{int next,to;}e[N];
  9 int n,m,f,root,cnt;
 10 int head[N],q[N<<1],s[N];
 11 int read()
 12 {
 13     int x=0,f=1;char c=getchar();
 14     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
 15     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
 16     return x*f;
 17 }
 18 void insert(int a,int b){cnt++;e[cnt].to=b;e[cnt].next=head[a];head[a]=cnt;}
 19 void dfs(int x)
 20 {
 21     q[++cnt]=x+1;
 22     for(int i=head[x];i;i=e[i].next)dfs(e[i].to);
 23     q[++cnt]=x+n+1;
 24 }
 25 void pushup(int x)
 26 {
 27     int l=tr[x].ch[0],r=tr[x].ch[1];
 28     tr[x].size=tr[l].size+tr[r].size+1;
 29     tr[x].num=tr[l].num+tr[r].num+tr[x].t;
 30     tr[x].sum=tr[l].sum+tr[r].sum+tr[x].v;
 31 }
 32 void pushdown(int x)
 33 {
 34     int l=tr[x].ch[0],r=tr[x].ch[1];long long tag=tr[x].tag;
 35     if(l)tr[l].tag+=tag,tr[l].sum+=tag*tr[l].num,tr[l].v+=tag*tr[l].t;
 36     if(r)tr[r].tag+=tag,tr[r].sum+=tag*tr[r].num,tr[r].v+=tag*tr[r].t;
 37     tr[x].tag=0;
 38 }
 39 void rotate(int x,int& k)
 40 {
 41     int y=tr[x].fa,z=tr[y].fa,l,r;
 42     if(tr[y].ch[0]==x)l=0;else l=1;r=l^1;
 43     if(y==k)k=x;
 44     else{if(tr[z].ch[0]==y)tr[z].ch[0]=x;else tr[z].ch[1]=x;}
 45     tr[x].fa=z;tr[y].fa=x;tr[tr[x].ch[r]].fa=y;
 46     tr[y].ch[l]=tr[x].ch[r];tr[x].ch[r]=y;
 47     pushup(y);pushup(x);
 48 }
 49 void splay(int x,int& k)
 50 {
 51     int top=0;s[++top]=x;
 52     for(int i=x;tr[i].fa;i=tr[i].fa)s[++top]=tr[i].fa;
 53     for(int i=top;i;i--)if(tr[s[i]].tag)pushdown(s[i]);
 54     while(x!=k)
 55     {
 56         int y=tr[x].fa,z=tr[y].fa;
 57         if(y!=k)
 58         {
 59             if((tr[y].ch[0]==x)^(tr[z].ch[0]==y))rotate(x,k);
 60             else rotate(y,k);
 61         }
 62         rotate(x,k);
 63     }
 64 }
 65 int fmin(int x){while(tr[x].ch[0])x=tr[x].ch[0];return x;}
 66 int fmax(int x){while(tr[x].ch[1])x=tr[x].ch[1];return x;}
 67 void split(int l,int r)
 68 {
 69     splay(l,root);int x=fmax(tr[l].ch[0]);
 70     splay(r,root);int y=fmin(tr[r].ch[1]);
 71     splay(x,root);splay(y,tr[x].ch[1]);
 72 }
 73 void build(int l,int r,int last)
 74 {
 75     if(l>r)return;
 76     int mid=(l+r)>>1;
 77     tr[q[mid]].fa=q[last];
 78     tr[q[last]].ch[mid>last]=q[mid];
 79     build(l,mid-1,mid);build(mid+1,r,mid);
 80     pushup(q[mid]);
 81 }
 82 void print(int x)
 83 {
 84     printf("[%d] [fa]%d [v]%lld [sum]%lld [t]%d [num]%d\\n",x,tr[x].fa,tr[x].v,tr[x].sum,tr[x].t,tr[x].num);
 85     int l=tr[x].ch[0],r=tr[x].ch[1];
 86     if(l)print(l);if(r)print(r);
 87 }
 88 void query()
 89 {
 90     int x=read();
 91     splay(x+1,root);
 92     printf("%lld\\n",tr[tr[x+1].ch[0]].sum+tr[x+1].v);
 93 }
 94 void change()
 95 {
 96     int x=read(),y=read();
 97     split(x+1,x+n+1);
 98     int yi=tr[root].ch[1],xi=tr[yi].ch[0];
 99     tr[yi].ch[0]=0;pushup(yi);pushup(root);
100     splay(y+1,root);
101     int u=fmin(tr[y+1].ch[1]);
102     splay(u,tr[y+1].ch[1]);
103     tr[xi].fa=u;
104     tr[u].ch[0]=xi;
105     pushup(u);pushup(root);
106 }
107 void add()
108 {
109     int x=read();long long tag=read();
110     split(x+1,x+n+1);
111     int yi=tr[root].ch[1],xi=tr[yi].ch[0];
112     tr[xi].tag+=tag;tr[xi].sum+=tag*tr[xi].num;tr[xi].v+=tag*tr[xi].t;
113     pushup(yi);pushup(root);
114 }
115 int main()
116 {
117     char str[1];
118     n=read();
119     for(int i=2;i<=n;i++)f=read(),insert(f,i);
120     for(int i=1;i<=n;i++)f=read(),tr[i+1].v=f,tr[i+1].t=1,tr[i+n+1].v=-f,tr[i+n+1].t=-1;
121     cnt=1;dfs(1);root=q[n+1];
122     q[1]=1;q[2*n+2]=2*n+2;
123     build(1,2*n+2,0);
124     m=read();
125     while(m--)
126     {
127         scanf("%s",str);
128         if(str[0]==Q)query();
129         if(str[0]==C)change();
130         if(str[0]==F)add();
131     }
132     return 0;
133 }
View Code
技术分享图片
  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 using namespace std;
  5 const int N=100010;
  6 struct node{int ch[2],fa,t,num;long long v,sum,tag;}tr[N<<1];
  7 struct edge{int next,to;}e[N];
  8 int n,m,f,root,cnt;
  9 int head[N],q[N<<1],s[N<<1];
 10 int read()
 11 {
 12     int x=0,f=1;char c=getchar();
 13     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
 14     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
 15     return x*f;
 16 }
 17 void insert(int a,int b){cnt++;e[cnt].to=b;e[cnt].next=head[a];head[a]=cnt;}
 18 void dfs(int x)
 19 {
 20     q[++cnt]=x+1;
 21     for(int i=head[x];i;i=e[i].next)dfs(e[i].to);
 22     q[++cnt]=x+n+1;
 23 }
 24 void add(int x,long long tag){tr[x].sum+=tag*tr[x].num;tr[x].v+=tag*tr[x].t;}
 25 void pushup(int x)
 26 {
 27     int l=tr[x].ch[0],r=tr[x].ch[1];
 28     tr[x].num=tr[l].num+tr[r].num+tr[x].t;
 29     tr[x].sum=tr[l].sum+tr[r].sum+tr[x].v;
 30 }
 31 void pushdown(int x)
 32 {
 33     int l=tr[x].ch[0],r=tr[x].ch[1];long long tag=tr[x].tag;
 34     if(l)tr[l].tag+=tag,add(l,tag);
 35     if(r)tr[r].tag+=tag,add(r,tag);
 36     tr[x].tag=0;
 37 }
 38 void rotate(int x,int& k)
 39 {
 40     int y=tr[x].fa,z=tr[y].fa,l,r;
 41     if(tr[y].ch[0]==x)l=0;else l=1;r=l^1;
 42     if(y==k)k=x;
 43     else{if(tr[z].ch[0]==y)tr[z].ch[0]=x;else tr[z].ch[1]=x;}
 44     tr[x].fa=z;tr[y].fa=x;tr[tr[x].ch[r]].fa=y;
 45     tr[y].ch[l]=tr[x].ch[r];tr[x].ch[r]=y;
 46     pushup(y);pushup(x);
 47 }
 48 void splay(int x,int& k)
 49 {
 50     int top=0;s[++top]=x;
 51     for(int i=x;tr[i].fa;i=tr[i].fa)s[++top]=tr[i].fa;
 52     for(int i=top;i;i--)if(tr[s[i]].tag)pushdown(s[i]);
 53     while(x!=k)
 54     {
 55         int y=tr[x].fa,z=tr[y].fa;
 56         if(y!=k)
 57         {
 58             if((tr[y].ch[0]==x)^(tr[z].ch[0]==y))rotate(x,k);
 59             else rotate(y,k);
 60         }
 61         rotate(x,k);
 62     }
 63 }
 64 int find(int x){while(tr[x].ch[1])x=tr[x].ch[1];return x;}
 65 void build(int l,int r,int last)
 66 {
 67     if(l>r)return;
 68     int mid=(l+r)>>1;
 69     tr[q[mid]].fa=q[last];
 70     tr[q[last]].ch[mid>last]=q[mid];
 71     build(l,mid-1,mid);build(mid+1,r,mid);
 72     pushup(q[mid]);
 73 }
 74 int merge(int r1,int r2)
 75 {
 76     int w=find(r1);
 77     splay(w,r1);
 78     tr[w].ch[1]=r2;
 79     tr[r2].fa=w;
 80     pushup(w);
 81     return w;
 82 }
 83 void cutl(int x,int rt,int& r1,int& r2)
 84 {
 85     splay(x,rt);
 86     r1=tr[x].ch[0];r2=x;
 87     tr[x].ch[0]=0;
 88     tr[r1].fa=0;
 89     pushup(x);
 90 }
 91 void cutr(int x,int rt,int& r1,int& r2)
 92 {
 93     splay(x,rt);
 94     r1=x;r2=tr[x].ch[1];
 95     tr[x].ch[1]=0;
 96     tr[r2].fa=0;
 97     pushup(x);
 98 }
 99 void query()
100 {
101     int x=read()+1;
102     splay(x,root);
103     printf("%lld\\n",tr[tr[x].ch[0]].sum+tr[x].v);
104 }
105 void change()
106 {
107     int x=read()+1,y=x+n,k=read()+1,p1,p2,p3;
108     cutl(x,root,p1,p2);
109     cutr(y,p2,p2,p3);
110     cutr(k,merge(p1,p3),p1,p3);
111     root=merge(merge(p1,p2),p3);
112 }
113 void add()
114 {
115     int x=read()+1,y=x+n;long long tag=read();
116     splay(x,root);splay(y,tr[x].ch[1]);
117     int z=tr[y].ch[0];
118     add(x,tag);add(y,tag);
119     add(z,tag);tr[z].tag+=tag;
120     pushup(y);pushup(x);
121 }
122 int main()
123 {
124     char str[5];
125     n=read();
126     for(int i=2;i<=n;i++)f=read(),insert(f,i);
127     for(int i=2;i<=n+1;i++)f=read(),tr[i].v=f,tr[i].t=1,tr[i+n].v=-f,tr[i+n].t=-1;
128     cnt=0;q[++cnt]=1;dfs(1);q[++cnt]=2*n+2;
129     build(1,2*n+2,0);root=q[n+1];
130     m=read();
131     while(m--)
132     {
133         scanf("%s",str);
134         if(str[0]==Q)query();
135         if(str[0]==C)change();
136         if(str[0]==F)add();
137     }
138     return 0;
139 }
View Code

2.【bzoj1500】[NOI2005]维修数列

题意:见原题

分析:Zsnuoの博客

技术分享图片
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<queue>
  5 using namespace std;
  6 const int inf=0x3f3f3f3f;
  7 const int N=1000005;
  8 queue<int>q;
  9 int n,m,root,cnt;
 10 int tr[N][2],id[N],a[N],size[N],sum[N],v[N],mx[N],lx[N],rx[N],fa[N];
 11 bool tag[N],rev[N];
 12 int read()
 13 {
 14     int x=0,f=1;char c=getchar();
 15     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
 16     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
 17     return x*f;
 18 }
 19 void update(int x)
 20 {
 21     int l=tr[x][0],r=tr[x][1];
 22     sum[x]=sum[l]+sum[r]+v[x];
 23     size[x]=size[l]+size[r]+1;
 24     mx[x]=max(mx[l],mx[r]);
 25     mx[x]=max(mx[x],rx[l]+v[x]+lx[r]);
 26     lx[x]=max(lx[l],sum[l]+v[x]+lx[r]);
 27     rx[x]=max(rx[r],sum[r]+v[x]+rx[l]);
 28 }
 29 void pushdown(int x)
 30 {
 31     int l=tr[x][0],r=tr[x][1];
 32     if(tag[x])
 33     {
 34         rev[x]=tag[x]=0;
 35         if(l)tag[l]=1,v[l]=v[x],sum[l]=v[x]*size[l];
 36         if(r)tag[r]=1,v[r]=v[x],sum[r]=v[x]*size[r];
 37         if(v[x]>=0)
 38         {
 39             if(l)mx[l]=lx[l]=rx[l]=sum[l];
 40             if(r)mx[r]=lx[r]=rx[r]=sum[r];
 41         }
 42         else
 43         {
 44             if(l)lx[l]=rx[l]=0,mx[l]=v[x];
 45             if(r)lx[r]=rx[r]=0,mx[r]=v[x];
 46         }
 47     }
 48     if(rev[x])
 49     {
 50         rev[x]^=1;rev[l]^=1;rev[r]^=1;
 51         swap(lx[l],rx[l]);swap(lx[r],rx[r]);
 52         swap(tr[l][0],tr[l][1]);swap(tr[r][0],tr[r][1]);
 53     }
 54 }
 55 void rotate(int x,int& k)
 56 {
 57     int y=fa[x],z=fa[y],l,r;
 58     l=(tr[y][1]==x);r=l^1;
 59     if(y==k)k=x;
 60     else tr[z][tr[z][1]==y]=x;
 61     fa[x]=z;fa[y]=x;fa[tr[x][r]]=y;
 62     tr[y][l]=tr[x][r];tr[x][r]=y;
 63     update(y);update(x);
 64 }
 65 void splay(int x,int& k)
 66 {
 67     while(x!=k)
 68     {
 69         int y=fa[x],z=fa[y];
 70         if(y!=k)
 71         {
 72             if((tr[y][0]==x)^(tr[z][0]==y))rotate(x,k);
 73             else rotate(y,k);
 74         }
 75         rotate(x,k);
 76     }
 77 }
 78 int find(int x,int rnk)
 79 {
 80     pushdown(x);
 81     int l=tr[x][0],r=tr[x][1];
 82     if(size[l]+1==rnk)return x;
 83     else if(size[l]>=rnk)return find(l,rnk);
 84     else return find(r,rnk-size[l]-1);
 85 }
 86 int turn(int k,int tot)
 87 {
 88     int x=find(root,k),y=find(root,k+tot+1);
 89     splay(x,root);splay(y,tr[x][1]);
 90     return tr[y][0];
 91 }
 92 void build(int l,int r,int f)
 93 {
 94     if(l>r)return;
 95     int mid=(l+r)>>1,now=id[mid],last=id[f];
 96     if(l==r)
 97     {
 98         sum[now]=a[l];size[now]=1;tag[now]=rev[now]=0;
 99         if(a[l]>=0)lx[now]=rx[now]=mx[now]=a[l];
100         else lx[now]=rx[now]=0,mx[now]=a[l];
101     }
102     else build(l,mid-1,mid),build(mid+1,r,mid);
103     v[now]=a[mid];fa[now]=last;update(now);
104     tr[last][mid>=f]=now;
105 }
106 void insert(int k,int tot)
107 {
108     for(int i=1;i<=tot;i++)a[i]=read();
109     for(int i=1;i<=tot;i++)
110         if(!q.empty())id[i]=q.front(),q.pop();
111         else id[i]=++cnt;
112     build(1,tot,0);int rt=id[(1+tot)>>1];
113     int x=find(root,k+1),y=find(root,k+2);
114     splay(x,root);splay(y,tr[x][1]);
115     tr[y][0]=rt;fa[rt]=y;
116     update(y);update(x);
117 }
118 void rec(int x)
119 {
120     if(!x)return;
121     int l=tr[x][0],r=tr[x][1];
122     rec(l);rec(r);q.push(x);
123     fa[x]=tr[x][0]=tr[x][1]=0;
124     tag[x]=rev[x]=0;
125 }
126 void erase(int k,int tot)
127 {
128     int x=turn(k,tot),y=fa[x];
129     rec(x);tr[y][0]=0;
130     update(y);update(fa[y]);
131 }
132 void makesame(int k,int tot,int val)
133 {
134     int x=turn(k,tot),y=fa[x];
135     tag[x]=1;v[x]=val;sum[x]=val*size[x];
136     if(val>=0)lx[x]=rx[x]=mx[x]=sum[x];
137     else lx[x]=rx[x]=0,mx[x]=val;
138     update(y);update(fa[y]);
139 }
140 void rever(int k,int tot)
141 {
142     int x=turn(k,tot),y=fa[x];
143     if(!tag[x])
144     {
145         rev[x]^=1;
146         swap(tr[x][0],tr[x][1]);
147         swap(lx[x],rx[x]);
148         update(y);update(fa[y]);
149     }
150 }
151 void query(int k,int tot)
152 {
153     int x=turn(k,tot);
154     printf("%d\\n",sum[x]);
155 }
156 int main()
157 {
158     n=read();m=read();
159     mx[0]=a[1]=a[n+2]=-inf;
160     for(int i=1;i<=n;i++)a[i+1]=read();
161     for(int i=1;i<=n+2;i++)id[i]=i;
162     root=(n+3)>>1;cnt=n+2;
163     build(1,n+2,0);
164     int k,tot,val;
165     char s[15];
166     while(m--)
167     {
168         scanf("%s",s);
169         if(s[0]!=M||s[2]!=X)k=read(),tot=read();
170         if(s[0]==I)insert(k,tot);
171         else if(s[0]==D)erase(k,tot);
172         else if(s[0]==M)
173         {
174             if(s[2]==X)printf("%d\\n",mx[root]);
175             else val=read(),makesame(k,tot,val);
176         }
177         else if(s[0]==R)rever(k,tot);
178         else query(k,tot);
179     }
180     return 0;
181 }
View Code

【treap】

〖模板代码

技术分享图片
 1 void update(int k){tr[k].s=tr[tr[k].l].s+tr[tr[k].r].s+tr[k].w;}
 2 void lturn(int& k)
 3 {
 4     int t=tr[k].r;tr[k].r=tr[t].l;tr[t].l=k;
 5     tr[t].s=tr[k].s;update(k);k=t;
 6 }
 7 void rturn(int& k)
 8 {
 9     int t=tr[k].l;tr[k].l=tr[t].r;tr[t].r=k;
10     tr[t].s=tr[k].s;update(k);k=t;
11 }
12 void insert(int& k,int x)
13 {
14     if(k==0){k=++cnt;tr[k].w=tr[k].s=1;tr[k].rnd=rand();tr[k].v=x;return;}
15     tr[k].s++;
16     if(x==tr[k].v)tr[k].w++;
17     else if(x<tr[k].v){insert(tr[k].l,x);if(tr[tr[k].l].rnd<tr[k].rnd)rturn(k);}
18     else {insert(tr[k].r,x);if(tr[tr[k].r].rnd<tr[k].rnd)lturn(k);}
19 }
20 void del(int& k,int x)
21 {
22     if(k==0)return;
23     if(tr[k].v==x)
24     {
25         if(tr[k].w>1)tr[k].w--,tr[k].s--;
26         else if(tr[k].l*tr[k].r==0)k=tr[k].l+tr[k].r;
27         else if(tr[tr[k].l].rnd<tr[tr[k].r].rnd)rturn(k),del(k,x);
28         else lturn(k),del(k,x);
29     }
30     else if(x<tr[k].v)tr[k].s--,del(tr[k].l,x);
31     else tr[k].s--,del(tr[k].r,x);
32 }
33 int askrank(int k,int x)
34 {
35     if(k==0)return 0;
36     if(tr[k].v==x)return tr[tr[k].l].s+1;
37     else if(x<tr[k].v)return askrank(tr[k].l,x);
38     else return tr[tr[k].l].s+tr[k].w+askrank(tr[k].r,x);
39 }
40 int asknum(int k,int x)
41 {
42     if(k==0)return 0;
43     if(x<=tr[tr[k].l].s)return asknum(tr[k].l,x);
44     else if(x>tr[tr[k].l].s+tr[k].w)return asknum(tr[k].r,x-tr[tr[k].l].s-tr[k].w);
45     else return tr[k].v;
46 }
47 void askbefore(int k,int x)
48 {
49     if(k==0)return;
50     if(tr[k].v<x)ans=tr[k].v,askbefore(tr[k].r,x);
51     else askbefore(tr[k].l,x);
52 }
53 void askafter(int k,int x)
54 {
55     if(k==0)return;
56     if(tr[k].v>x)ans=tr[k].v,askafter(tr[k].l,x);
57     else askafter(tr[k].r,x);
58 }
View Code

【线段树】

〖模板代码

技术分享图片
 1 void up(int x)
 2 {
 3     sum[x]=sum[l(x)]+sum[r(x)];
 4     mx[x]=max(mx[l(x)],mx[r(x)]);
 5     mn[x]=min(mn[l(x)],mn[r(x)]);
 6 }
 7 void cset(int x,int l,int r,ll mark)
 8 {
 9     set[x]=mark;add[x]=0;f[x]=true;
10     sum[x]=mark*(r-l+1);
11     mx[x]=mn[x]=mark;
12 }
13 void cadd(int x,int l,int r,ll mark)
14 {
15     add[x]+=mark;
16     sum[x]+=mark*(r-l+1);
17     mx[x]+=mark;mn[x]+=mark;
18 }
19 void start(int x,int l,int r)
20 {
21     int mid=(l+r)>>1;
22     if(f[x])
23     {
24         cset(l(x),l,mid,set[x]);
25         cset(r(x),mid+1,r,set[x]);
26         set[x]=0;f[x]=false;
27     }
28     if(add[x])
29     {
30         cadd(l(x),l,mid,add[x]);
31         cadd(r(x),mid+1,r,add[x]);
32         add[x]=0;
33     }
34 }
35 void build(int x,int l,int r)
36 {
37     if(l==r)
38     {
39         sum[x]=read();
40         mn[x]=mx[x]=sum[x];
41         return;
42     }
43     int mid=(l+r)>>1;
44     build(l(x),l,mid);
45     build(r(x),mid+1,r);
46     if(l!=r)up(x);
47 }
48 void change(int x,int l,int r,ll mark,int p)
49 {
50     if(l!=r)start(x,l,r);
51     if(L<=l&&R>=r)
52     {
53         if(p==1)cadd(x,l,r,mark);
54         if(p==2)cset(x,l,r,mark);
55         return;
56     }
57     int mid=(l+r)>>1;
58     if(L<=mid)change(l(x),l,mid,mark,p);
59     if(R>mid)change(r(x),mid+1,r,mark,p);
60     if(l!=r)up(x);
61 }
62 void ask(int x,int l,int r,int p)
63 {
64     if(l!=r)start(x,l,r);
65     if(L<=l&&R>=r)
66     {
67         if(p==1)ans=max(ans,mx[x]);
68         if(p==2)ans=min(ans,mn[x]);
69         if(p==3)ans+=sum[x];
70         return;
71     }
72     int mid=(l+r)>>1;
73     if(L<=mid)ask(l(x),l,mid,p);
74     if(R>mid)ask(r(x),mid+1,r,p);
75 }
View Code

〖相关题目

1.【codeforces788E】New Task

题意:n个数,初始属性为1。m个操作,每个操作可以改变一个数字的属性为0或1。每次操作后,求有多少子序列满足要求:a<b<c<d<e,且Xa≤Xb=Xc=Xd≥Xe,b,c,d属性为1,a,e属性任意。

分析:Zsnuoの博客

技术分享图片
  1 #include<cstdio>
  2 #include<algorithm> 
  3 #include<cstring>
  4 #define LL long long
  5 using namespace std;
  6 const int N=1e5+10;
  7 const int mod=1e9+7;
  8 int n,m,cnt,sum,x,y,last;
  9 int num[N],t[N],L[N],R[N],root[N],s[N],p[N],ans;
 10 struct node{int w,pos;}a[N];
 11 struct tree{int l,r,sz,s[6];}tr[N*10];
 12 int read()
 13 {
 14     int x=0,f=1;char c=getchar();
 15     while(c<0||c>9){if(x==-)f=-1;c=getchar();}
 16     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
 17     return x*f;
 18 }
 19 bool cmp(node a,node b){return a.w==b.w?a.pos<b.pos:a.w<b.w;}
 20 int lowbit(int x){return x&(-x);}
 21 void insert(int x)
 22 {
 23     while(x<=n)
 24     {
 25         t[x]++;
 26         x+=lowbit(x);
 27     }
 28 }
 29 int query(int x)
 30 {
 31     int ans=0;
 32     while(x){ans+=t[x];x-=lowbit(x);}
 33     return ans;
 34 }
 35 void up(int x)
 36 {
 37     int l=tr[x].l,r=tr[x].r;
 38     tr[x].sz=(tr[l].sz+tr[r].sz)%mod;
 39     tr[x].s[1]=(tr[l].s[1]+tr[r].s[1])%mod;
 40     tr[x].s[5]=(tr[l].s[5]+tr[r].s[5])%mod;
 41     tr[x].s[2]=(tr[l].s[2]+tr[r].s[2]+(LL)tr[l].s[1]*tr[r].sz)%mod;
 42     tr[x].s[4]=(tr[l].s[4]+tr[r].s[4]+(LL)tr[l].sz*tr[r].s[5])%mod;
 43     tr[x].s[3]=(tr[l].s[3]+tr[r].s[3]+(LL)tr[l].s[1]*tr[r].s[4]+(LL)tr[l].s[2]*tr[r].s[5])%mod;
 44     //LL!!! 
 45 }
 46 void change(int &x,int l,int r,int pos,int v)
 47 {
 48     if(x==0)x=++sum;
 49     if(l==r)
 50     {
 51         tr[x].sz=v*1;
 52         tr[x].s[1]=v*L[pos];
 53         tr[x].s[5]=v*R[pos];
 54         tr[x].s[2]=tr[x].s[3]=tr[x].s[4]=0;
 55         tr[x].l=tr[x].r=0;
 56         return;
 57     }
 58     else
 59     {
 60         int mid=(l+r)>>1;
 61         if(p[pos]<=mid)change(tr[x].l,l,mid,pos,v);
 62         else change(tr[x].r,mid+1,r,pos,v);
 63         up(x);
 64     }
 65 }
 66 int main()
 67 {
 68     n=read();
 69     for(int i=1;i<=n;i++)
 70         a[i].w=read(),a[i].pos=i;
 71     sort(a+1,a+n+1,cmp);
 72     for(int i=1;i<=n;i++)
 73     {
 74         if(a[i].w!=a[i-1].w)
 75         {
 76             if(cnt)s[cnt]=i-1-last;
 77             last=i-1;
 78             cnt++;
 79         }
 80         num[a[i].pos]=cnt;
 81         p[a[i].pos]=i-last;
 82     }
 83     s[cnt]=n-last;
 84     for(int i=1;i<=n;i++)
 85         L[i]=query(num[i]),insert(num[i]);
 86     memset(t,0,sizeof(t));
 87     for(int i=n;i>=1;i--)
 88         R[i]=query(num[i]),insert(num[i]);
 89     for(int i=1;i<=n;i++)
 90     {
 91         ans=(ans-tr[root[num[i]]].s[3]+mod)%mod;
 92         change(root[num[i]],1,s[num[i]],i,1);
 93         ans=(ans+tr[root[num[i]]].s[3])%mod;
 94     }
 95     m=read();
 96     for(int i=1;i<=m;i++)
 97     {
 98         x=read();y=read();
 99         ans=(ans-tr[root[num[y]]].s[3]+mod)%mod;
100         change(root[num[y]],1,s[num[y]],y,x-1);
101         ans=(ans+tr[root[num[y]]].s[3])%mod;
102         printf("%d\\n",ans);
103     }
104     return 0;
105 }
View Code

2.【bzoj4756】[Usaco2017 Jan] Promotion Counting

题意:见原题

分析:线段树合并的裸题

技术分享图片
 1 #include<cstdio>
 2 #include<algorithm> 
 3 #include<cstring>
 4 #define LL long long
 5 using namespace std;
 6 const int N=1e5+10;
 7 int n,cnt,tot;
 8 int id[N],p[N],fa[N],first[N],ans[N],root[N];
 9 int ls[N*100],rs[N*100],tr[N*100];
10 struct edge{int to,next;}e[N];
11 int read()
12 {
13     int x=0,f=1;char c=getchar();
14     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
15     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
16     return x*f;
17 }
18 void ins(int u,int v){e[++tot]=(edge){v,first[u]};first[u]=tot;}
19 void insert(int l,int r,int& pos,int num,int w)
20 {
21     pos=++cnt;tr[pos]+=w;
22     if(l==r)return;
23     int mid=(l+r)>>1;
24     if(num<=mid)insert(l,mid,ls[pos],num,w);
25     else insert(mid+1,r,rs[pos],num,w);
26 }
27 int merge(int now,int last)
28 {
29     if(!now||!last)return now^last;//子树为空就直接并上去 
30     ls[now]=merge(ls[now],ls[last]);
31     rs[now]=merge(rs[now],rs[last]);
32     tr[now]=tr[ls[now]]+tr[rs[now]];
33     return now;
34 }
35 int query(int l,int r,int pos,int L,int R)
36 {
37     if(L<=l&&R>=r)return tr[pos];
38     int sum=0,mid=(l+r)>>1;
39     if(L<=mid)sum+=query(l,mid,ls[pos],L,R);
40     if(R>mid)sum+=query(mid+1,r,rs[pos],L,R);
41     return sum;
42 }
43 void dfs(int x)
44 {
45     insert(1,n,root[x],id[x],1);
46     for(int i=first[x];i;i=e[i].next)dfs(e[i].to);
47     for(int i=first[x];i;i=e[i].next)root[x]=merge(root[x],root[e[i].to]);
48     ans[x]=query(1,n,root[x],id[x]+1,n);
49 }
50 int main()
51 {
52     n=read();
53     for(int i=1;i<=n;i++)id[i]=p[i]=read();
54     sort(p+1,p+n+1);
55     for(int i=1;i<=n;i++)id[i]=lower_bound(p+1,p+n+1,id[i])-p;
56     for(int i=2;i<=n;i++)fa[i]=read(),ins(fa[i],i);
57     dfs(1);
58     for(int i=1;i<=n;i++)printf("%d\\n",ans[i]);
59     return 0;
60 }
View Code

【树状数组】

〖模板代码

  [单点修改区间查询]

技术分享图片
1 int lowbit(int x){return x&(-x);}
2 void insert(int x,int p){while(x<=n)t[x]+=p,x+=lowbit(x);}
3 int query(int x){int ans=0;while(x)ans+=t[x],x-=lowbit(x);return ans;}
View Code

  [区间修改区间查询]

技术分享图片
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #define LL long long
 6 using namespace std;
 7 const int N=1e5+5;
 8 int n,m,op,L,R;
 9 LL tmp,x,tr[N][2];
10 LL read()
11 {
12     LL x=0,f=1;char c=getchar();
13     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
14     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
15     return x*f;
16 }
17 int lowbit(int x){return x&(-x);}
18 void add(int x,LL c,int id){while(x<=n)tr[x][id]+=c,x+=lowbit(x);}
19 void insert(int id,LL c){add(id,c,0);add(id,c*id,1);}
20 LL query(int x,int id){LL ans=0;while(x)ans+=tr[x][id],x-=lowbit(x);return ans;}
21 LL ask(int id){LL ans=(id+1)*query(id,0)-query(id,1);return ans;}
22 int main()
23 {
24     n=read();m=read();
25     for(int i=1;i<=n;i++)x=read(),insert(i,x-tmp),tmp=x;
26     while(m--)
27     {
28         op=read();
29         if(op==1)
30         {
31             L=read();R=read();x=read();
32             insert(L,x);insert(R+1,-x);
33         }
34         else
35         {
36             L=read();R=read();
37             printf("%lld\\n",ask(R)-ask(L-1));
38         }
39     }
40     return 0;
41 }
View Code

〖相关题目

1.【bzoj3173】[Tjoi2013]最长上升子序列

题意:给定一个初始为空的序列,现在将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置。每插入一个数字,求此时最长上升子序列长度。

分析:Zsnuoの博客

技术分享图片
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int N=1e5+5;
 6 int n,id,cnt,f[N],ans[N],a[N],num[N],bit[N];
 7 int read()
 8 {
 9     int x=0,f=1;char c=getchar();
10     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
11     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
12     return x*f;
13 }
14 int lowbit(int x){return x&(-x);}
15 void ins(int x){while(x<=n)bit[x]--,x+=lowbit(x);}
16 int pos(int x)
17 {
18     int now=0,ans=0;
19     for(int i=17;i>=0;i--)
20     {
21         now+=(1<<i);
22         if(now<n&&ans+bit[now]<x)ans+=bit[now];
23         else now-=(1<<i);
24     }
25     return now+1;
26 }
27 int main()
28 {
29     n=read();
30     for(int i=1;i<=n;i++)
31     {
32         a[i]=read();bit[i]++;
33         if(i+lowbit(i)<=n)bit[i+lowbit(i)]+=bit[i];
34     }
35     for(int i=n;i>=1;i--)
36         id=pos(a[i]+1),num[id]=i,ins(id);
37     for(int i=1;i<=n;i++)
38     {
39         id=lower_bound(f+1,f+cnt+1,num[i])-f;
40         if(id>cnt)f[++cnt]=num[i];
41         else f[id]=num[i];
42         ans[num[i]]=id;
43     }
44     for(int i=1;i<=n;i++)ans[i]=max(ans[i],ans[i-1]),printf("%d\\n",ans[i]);
45     return 0;
46 }
View Code

【堆】

〖模板代码

技术分享图片
 1 int main()
 2 {
 3     n=read();
 4     for(int i=1;i<=n;i++)
 5     {
 6         op=read();
 7         if(op==1)
 8         {
 9             a[++num]=read();tmp=num;
10             while(tmp!=1)
11             {
12                 if(a[tmp]<a[tmp/2])swap(a[tmp],a[tmp/2]);
13                 else break;tmp>>=1;
14             }
15         }
16         else if(op==2)printf("%d\\n",a[1]);
17         else
18         {
19             a[1]=a[num--];tmp=1;
20             while(tmp*2<=num)
21             {
22                 int next=tmp*2;
23                 if(a[next]>a[next+1]&&next+1<=num)next++;
24                 if(a[tmp]<=a[next])break;
25                 swap(a[tmp],a[next]);tmp=next;
26             }
27         }
28     }
29 }
View Code

【主席树】

〖相关题目

1.【bzoj2588】Spoj 10628. Count on a tree

题意:给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。

分析:Zsnuoの博客

技术分享图片
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #define LL long long
 5 using namespace std;
 6 const int N=1e5+5;
 7 int n,m,tot,x,y,rk,cnte,ind,cnt,temp,lastans;
 8 int v[N],tmp[N],first[N],id[N],num[N],root[N];
 9 int deep[N],fa[N][20];
10 struct node{int lc,rc,sum;}tr[N*20];
11 struct edge{int to,next;}e[N*2];
12 int read()
13 {
14     int x=0,f=1;char c=getchar();
15     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
16     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
17     return x*f;
18 }
19 void ins(int u,int v){e[++cnte]=(edge){v,first[u]};first[u]=cnte;}
20 void insert(int u,int v){ins(u,v);ins(v,u);}
21 void dfs(int x)
22 {
23     ind++;id[x]=ind;num[ind]=x;
24     for(int i=1;(1<<i)<=deep[x];i++)fa[x][i]=fa[fa[x][i-1]][i-1];
25     for(int i=first[x];i;i=e[i].next)
26     {
27         if(deep[e[i].to])continue;
28         fa[e[i].to][0]=x;deep[e[i].to]=deep[x]+1;dfs(e[i].to);
29     }
30 }
31 int lca(int ri,int rj)
32 {
33     if(deep[ri]<deep[rj])swap(ri,rj);
34     int d=deep[ri]-deep[rj];
35     for(int i=0;(1<<i)<=d;i++)if((1<<i)&d)ri=fa[ri][i];
36     if(ri==rj)return ri;
37     for(int i=17;i>=0;i--)
38         if((1<<i)<=deep[ri]&&fa[ri][i]!=fa[rj][i])
39             ri=fa[ri][i],rj=fa[rj][i];
40     return fa[ri][0];
41 }
42 void update(int &x,int last,int L,int R,int num)
43 {
44     x=++cnt;tr[x].sum=tr[last].sum+1;
45     if(L==R)return;
46     tr[x].lc=tr[last].lc;tr[x].rc=tr[last].rc;
47     int mid=(L+R)>>1;
48     if(num<=mid)update(tr[x].lc,tr[last].lc,L,mid,num);
49     else update(tr[x].rc,tr[last].rc,mid+1,R,num);
50 }
51 int query(int x,int y,int rk)
52 {
53     int a=x,b=y,c=lca(x,y),d=fa[c][0];
54     a=root[id[x]];b=root[id[b]];c=root[id[c]];d=root[id[d]];
55     int L=1,R=tot;
56     while(L<R)
57     {
58         int mid=(L+R)>>1;
59         temp=tr[tr[a].lc].sum+tr[tr[b].lc].sum-tr[tr[c].lc].sum-tr[tr[d].lc].sum;
60         if(temp>=rk)R=mid,a=tr[a].lc,b=tr[b].lc,c=tr[c].lc,d=tr[d].lc;
61         else rk-=temp,L=mid+1,a=tr[a].rc,b=tr[b].rc,c=tr[c].rc,d=tr[d].rc;
62     }
63     return tmp[L];
64 }
65 int main()
66 {
67     n=read();m=read();
68     for(int i=1;i<=n;i++)v[i]=tmp[i]=read();
69     sort(tmp+1,tmp+n+1);tot=unique(tmp+1,tmp+n+1)-tmp-1;
70     for(int i=1;i<=n;i++)v[i]=lower_bound(tmp+1,tmp+tot+1,v[i])-tmp;
71     for(int i=1;i<n;i++)x=read(),y=read(),insert(x,y);
72     deep[1]=1;dfs(1);
73     for(int i=1;i<=n;i++)
74     {
75         temp=num[i];
76         update(root[i],root[id[fa[temp][0]]],1,tot,v[temp]);
77     }
78     for(int i=1;i<=m;i++)
79     {
80         x=read();y=read();rk=read();x^=lastans;
81         lastans=query(x,y,rk);printf("%d",lastans);
82         if(i!=m)printf("\\n");
83     }
84     return 0;
85 }
View Code

2.【bzoj3524】[Poi2014]Couriers

题意:给一个长度为n的序列a,m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2。如果存在,输出这个数,否则输出0。

分析:主席树裸题

技术分享图片
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int N=5e5+5;
 6 int n,m,sz,cnt,tmp,id,Li,Ri,a[N],b[N],rt[N];
 7 struct node{int sum,lc,rc;}tr[N*20];
 8 int read()
 9 {
10     int x=0,f=1;char c=getchar();
11     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
12     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
13     return x*f;
14 }
15 void build(int& root,int L,int R)
16 {
17     root=++cnt;tr[root].sum=0;
18     if(L==R)return;int mid=(L+R)>>1;
19     build(tr[root].lc,L,mid);build(tr[root].rc,mid+1,R);
20 }
21 void up(int& root,int L,int R,int last,int num)
22 {
23     root=++cnt;tr[root]=(node){tr[last].sum+1,tr[last].lc,tr[last].rc};
24     if(L==R)return;int mid=(L+R)>>1;
25     if(num<=mid)up(tr[root].lc,L,mid,tr[last].lc,num);
26     else up(tr[root].rc,mid+1,R,tr[last].rc,num);
27 }
28 int query(int ql,int qr,int L,int R,int K)
29 {
30     if(L==R){if(tr[qr].sum-tr[ql].sum>=K)return L;return 0;}
31     int mid=(L+R)>>1;
32     tmp=tr[tr[qr].lc].sum-tr[tr[ql].lc].sum;
33     if(tmp>=K)return query(tr[ql].lc,tr[qr].lc,L,mid,K);
34     else return query(tr[ql].rc,tr[qr].rc,mid+1,R,K);
35 }
36 void work()
37 {
38     Li=read();Ri=read();
39     id=query(rt[Li-1],rt[Ri],1,sz,(Ri-Li+1)/2+1);
40     printf("%d\\n",b[id]);
41 }
42 int main()
43 {
44     n=read();m=read();
45     for(int i=1;i<=n;i++)a[i]=b[i]=read();
46     sort(b+1,b+n+1);sz=unique(b+1,b+n+1)-b-1;
47     build(rt[0],1,sz);
48     for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+sz+1,a[i])-b;
49     for(int i=1;i<=n;i++)up(rt[i],1,sz,rt[i-1],a[i]);
50     while(m--)work();
51     return 0;
52 }
View Code

3.【bzoj1901】Zju2112 Dynamic Rankings

题意:给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。

分析:带修改的主席树

技术分享图片
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #define LL long long
 5 using namespace std;
 6 const int N=2e4+5;
 7 int n,m,cnt,tot,id,tx,ty;
 8 int A[N],B[N],C[N],a[N],tmp[N],rt[N],xx[N],yy[N];
 9 int lc[N*200],rc[N*200],sum[N*200];
10 char op[3];
11 int read()
12 {
13     int x=0,f=1;char c=getchar();
14     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
15     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
16     return x*f;
17 }
18 int lowbit(int x){return x&(-x);}
19 void ins(int& x,int last,int L,int R,int num,int c)
20 {
21     x=++tot;lc[x]=lc[last];rc[x]=rc[last];sum[x]=sum[last]+c;
22     if(L==R)return;int mid=(L+R)>>1;
23     if(num<=mid)ins(lc[x],lc[last],L,mid,num,c);
24     else ins(rc[x],rc[last],mid+1,R,num,c);
25 }
26 void add(int x,int c)
27 {
28     id=lower_bound(tmp+1,tmp+cnt+1,a[x])-tmp;
29     for(int i=x;i<=n;i+=lowbit(i))ins(rt[i],rt[i],1,cnt,id,c);
30 }
31 int query(int L,int R,int num)
32 {
33     if(L==R)return L;
34     int ans=0,mid=(L+R)>>1;
35     for(int i=1;i<=tx;i++)ans-=sum[lc[xx[i]]];
36     for(int i=1;i<=ty;i++)ans+=sum[lc[yy[i]]];
37     if(num<=ans)
38     {
39         for(int i=1;i<=tx;i++)xx[i]=lc[xx[i]];
40         for(int i=1;i<=ty;i++)yy[i]=lc[yy[i]];
41         return query(L,mid,num);
42     }
43     else
44     {
45         for(int i=1;i<=tx;i++)xx[i]=rc[xx[i]];
46         for(int i=1;i<=ty;i++)yy[i]=rc[yy[i]];
47         return query(mid+1,R,num-ans);
48     }
49 }
50 int main()
51 {
52     n=read();m=read();cnt=n;
53     for(int i=1;i<=n;i++)tmp[i]=a[i]=read();
54     for(int i=1;i<=m;i++)
55     {
56         scanf("%s",op+1);
57         A[i]=read();B[i]=read();
58         if(op[1]==Q)C[i]=read();
59         else tmp[++cnt]=B[i];
60     }
61     sort(tmp+1,tmp+cnt+1);
62     cnt=unique(tmp+1,tmp+cnt+1)-tmp-1;
63     for(int i=1;i<=n;i++)add(i,1);
64     for(int i=1;i<=m;i++)
65         if(C[i])
66         {
67             tx=ty=0;
68             for(int j=A[i]-1;j;j-=lowbit(j))xx[++tx]=rt[j];
69             for(int j=B[i];j;j-=lowbit(j))yy[++ty]=rt[j];
70             printf("%d\\n",tmp[query(1,cnt,C[i])]);
71         }
72         else add(A[i],-1),a[A[i]]=B[i],add(A[i],1);
73     return 0;
74 }
View Code

【fhq-treap】

〖模板代码

  [单点插入、单点删除、查排名、查前驱后继]

技术分享图片
 1 const int N=1e5+5;
 2 int n,op,now,root,ans,cnt,ch[N][5];
 3 #define lc ch][0
 4 #define rc ch][1
 5 #define rnd ch][2
 6 #define sz ch][3
 7 #define v ch][4
 8 int read()
 9 {
10     int x=0,f=1;char c=getchar();
11     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
12     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
13     return x*f;
14 }
15 void up(int w){w[sz]=w[lc][sz]+w[rc][sz]+1;}
16 void dn(int w){}
17 void split(int w,int& l,int& r,int k)
18 {
19     if(!w){l=r=0;return;}
20     dn(w);int lson=w[lc][sz];
21     if(k<=lson){r=w;split(w[lc],l,w[lc],k);}
22     else {l=w;split(w[rc],w[rc],r,k-lson-1);}
23     up(w);
24 }
25 int merge(int a,int b)
26 {
27     if(!a||!b)return a+b;
28     if(a[rnd]<b[rnd]){dn(a);a[rc]=merge(a[rc],b);up(a);return a;}
29     else {dn(b);b[lc]=merge(a,b[lc]);up(b);return b;}
30 }
31 void ins(int& w,int x,int k)
32 {
33     dn(w);
34     if(x[rnd]<w[rnd]||!w){split(w,x[lc],x[rc],k);w=x;up(w);return;}
35     int lson=w[lc][sz];
36     if(k<=lson)ins(w[lc],x,k);
37     else ins(w[rc],x,k-lson-1);
38     up(w);
39 }
40 void del(int& w,int k)
41 {
42     dn(w);
43     int lson=w[lc][sz];
44     if(k==lson+1){w=merge(w[lc],w[rc]);return;}
45     if(k<=lson)del(w[lc],k);
46     else del(w[rc],k-lson-1);
47     up(w);
48 }
49 int rank(int w,int t)
50 {
51     if(!w)return 0;
52     dn(w);
53     if(w[v]<t){return w[lc][sz]+1+rank(w[rc],t);}
54     else return rank(w[lc],t);
55 }
56 int numm(int w,int k)
57 {
58     dn(w);
59     int lson=w[lc][sz];
60     if(k==lson+1)return w[v];
61     if(k<=lson)return numm(w[lc],k);
62     else return numm(w[rc],k-lson-1);
63 }
64 void askb(int w,int t)
65 {
66     if(!w)return;
67     if(w[v]<t){ans=w[v];askb(w[rc],t);}
68     else askb(w[lc],t);
69 }
70 void aska(int w,int t)
71 {
72     if(!w)return;
73     if(w[v]>t){ans=w[v];aska(w[lc],t);}
74     else aska(w[rc],t);
75 }
View Code

  [线性建树、区间加、区间翻转、区间查询]

技术分享图片
 1 const int N=5e4+5;
 2 int n,m,root,op,L,R,V,ans;
 3 int rt1,rt2,rt3,st[N],ch[N][8];
 4 #define lc ch][0
 5 #define rc ch][1
 6 #define rnd ch][2
 7 #define sz ch][3
 8 #define v ch][4
 9 #define tag ch][5
10 #define rev ch][6
11 #define mx ch][7
12 void up(int w)
13 {
14     w[sz]=w[lc][sz]+w[rc][sz]+1;w[mx]=w[v];
15     if(w[lc])w[mx]=max(w[mx],w[lc][mx]);
16     if(w[rc])w[mx]=max(w[mx],w[rc][mx]);
17 }
18 void dn(int w)
19 {
20     if(w[tag])
21     {
22         w[lc][v]+=w[tag];w[lc][mx]+=w[tag];w[lc][tag]+=w[tag];
23         w[rc][v]+=w[tag];w[rc][mx]+=w[tag];w[rc][tag]+=w[tag];
24         w[tag]=0;
25     }
26     if(w[rev])
27     {
28         w[rev]^=1;w[lc][rev]^=1;w[rc][rev]^=1;
29         swap(w[lc][lc],w[lc][rc]);
30         swap(w[rc][lc],w[rc][rc]);
31     }
32 }
33 void dfs(int w){if(!w)return;dfs(w[lc]);dfs(w[rc]);up(w);}
34 int build(int n)
35 {
36     int top=0;
37     for(int w=1;w<=n;w++)
38     {
39         w[rnd]=rand();
40         while(top&&st[top][rnd]>w[rnd])
41         {
42             st[top][rc]=w[lc];
43             w[lc]=st[top--];
44         }
45         st[top][rc]=w;
46         st[++top]=w;
47     }
48     ch[0][1]=0;dfs(st[1]);
49     return st[1];
50 }
51 void split(int w,int& l,int& r,int k)
52 {
53     if(!w){l=r=0;return;}
54     dn(w);int lson=w[lc][sz];
55     if(k<=lson){r=w;split(w[lc],l,w[lc],k);}
56     else {l=w;split(w[rc],w[rc],r,k-lson-1);}
57     up(w);
58 }
59 int merge(int a,int b)
60 {
61     if(!a||!b)return a+b;
62     if(a[rnd]<b[rnd]){dn(a);a[rc]=merge(a[rc],b);up(a);return a;}
63     else {dn(b);b[lc]=merge(a,b[lc]);up(b);return b;}
64 }
65 void add(int L,int R,int V)
66 {
67     rt1=rt2=rt3=0;split(root,rt2,rt3,R);
68     root=rt2;rt2=0;split(root,rt1,rt2,L-1);
69     rt2[tag]+=V;rt2[v]+=V;rt2[mx]+=V;
70     root=merge(rt1,rt2);root=merge(root,rt3);
71 }
72 void rever(int L,int R)
73 {
74     rt1=rt2=rt3=0;split(root,rt2,rt3,R);
75     root=rt2;rt2=0;split(root,rt1,rt2,L-1);
76     rt2[rev]^=1;swap(rt2[lc],rt2[rc]);
77     root=merge(rt1,rt2);root=merge(root,rt3);
78 }
79 int query(int L,int R)
80 {
81     rt1=rt2=rt3=0;split(root,rt2,rt3,R);
82     root=rt2;rt2=0;split(root,rt1,rt2,L-1);
83     ans=rt2[mx];
84     root=merge(rt1,rt2);root=merge(root,rt3);
85     return ans;
86 }
View Code

  [查询历史版本]

技术分享图片
 1 int root[N],ch[N*50][5];
 2 #define lc ch][0
 3 #define rc ch][1
 4 #define rnd ch][2
 5 #define sz ch][3
 6 #define v ch][4
 7 int copy(int w)
 8 {
 9     cnt++;cnt[lc]=w[lc];cnt[rc]=w[rc];
10     cnt[rnd]=w[rnd];cnt[sz]=w[sz];cnt[v]=w[v];
11     return cnt;
12 }
13 int newnode(int val)
14 {
15     cnt++;cnt[sz]=1;cnt[v]=val;
16     cnt[rnd]=rand();return cnt;
17 }
18 void up(int w){w[sz]=w[lc][sz]+w[rc][sz]+1;}
19 void dn(int w){}
20 void split(int w,int& l,int& r,int val)
21 {
22     if(!w){l=r=0;return;}dn(w);
23     if(val<w[v]){r=copy(w);split(r[lc],l,r[lc],val);up(r);}
24     else {l=copy(w);split(l[rc],l[rc],r,val);up(l);}
25 }
26 int merge(int a,int b)
27 {
28     if(!a||!b)return a+b;
29     if(a[rnd]<b[rnd])
30     {
31         dn(a);int x=copy(a);
32         x[rc]=merge(x[rc],b);
33         up(x);return x;
34     }
35     else
36     {
37         dn(b);int x=copy(b);
38         x[lc]=merge(a,x[lc]);
39         up(x);return x;
40     }
41 }
42 void ins(int id,int val)
43 {
44     rt1=rt2=rt3=0;split(root[id],rt1,rt3,val);
45     rt2=newnode(val);root[id]=merge(merge(rt1,rt2),rt3);
46 }
47 void del(int id,int val)
48 {
49     rt1=rt2=rt3=0;
50     split(root[id],rt1,rt3,val);
51     root[id]=rt1;rt1=0;
52     split(root[id],rt1,rt2,val-1);
53     rt2=merge(rt2[lc],rt2[rc]);
54     root[id]=merge(merge(rt1,rt2),rt3);
55 }
56 int getkth(int id,int val)
57 {
58     rt1=rt2=0;split(root[id],rt1,rt2,val-1);
59     int ans=rt1[sz]+1;
60     root[id]=merge(rt1,rt2);
61     return ans;
62 }
63 int getval(int w,int k)
64 {
65     dn(w);int lson=w[lc][sz];
66     if(k==lson+1)return w[v];
67     if(k<=lson)return getval(w[lc],k);
68     else return getval(w[rc],k-lson-1);
69 }
70 void getpre(int w,int val)
71 {
72     if(!w)return;
73     if(w[v]<val)ans=w[v],getpre(w[rc],val);
74     else getpre(w[lc],val);
75 }
76 void getnext(int w,int val)
77 {
78     if(!w)return;
79     if(w[v]>val)ans=w[v],getnext(w[lc],val);
80     else getnext(w[rc],val);
81 }
View Code

〖相关题目

1.【bzoj3173】[Tjoi2013]最长上升子序列

题意:给定一个初始为空的序列,现在将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置。每插入一个数字,求此时最长上升子序列长度。

分析:Zsnuoの博客

技术分享图片
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cstdlib>
 5 using namespace std;
 6 const int N=1e5+5;
 7 int n,root,cnt,rt1,rt2,pos,ch[N][6];
 8 #define lc ch][0
 9 #define rc ch][1
10 #define rnd ch][2
11 #define sz ch][3
12 #define v ch][4
13 #define mx ch][5
14 int read()
15 {
16     int x=0,f=1;char c=getchar();
17     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
18     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
19     return x*f;
20 }
21 void up(int w)
22 {
23     w[sz]=w[lc][sz]+w[rc][sz]+1;
24     w[mx]=max(w[lc][mx],w[rc][mx]);
25     w[mx]=max(w[mx],w[v]);
26 }
27 void split(int w,int& l,int& r,int k)
28 {
29     if(!w){l=r=0;return;}
30     int lson=w[lc][sz];
31     if(k<=lson){r=w;split(w[lc],l,w[lc],k);}
32     else {l=w;split(w[rc],w[rc],r,k-lson-1);}
33     up(w);
34 }
35 int merge(int a,int b)
36 {
37     if(!a||!b)return a+b;
38     if(a[rnd]<b[rnd]){a[rc]=merge(a[rc],b);up(a);return a;}
39     else {b[lc]=merge(a,b[lc]);up(b);return b;}
40 }
41 void ins(int& w,int x,int k)
42 {
43     if(x[rnd]<w[rnd]||!w){split(w,x[lc],x[rc],k);w=x;up(w);return;}
44     int lson=w[lc][sz];
45     if(k<=lson)ins(w[lc],x,k);
46     else ins(w[rc],x,k-lson-1);
47     up(w);
48 }
49 int query(int pos)
50 {
51     rt1=rt2=0;split(root,rt1,rt2,pos);
52     int ans=rt1[mx];root=merge(rt1,rt2);
53     return ans;
54 }
55 int main()
56 {
57     n=read();
58     for(int i=1;i<=n;i++)
59     {
60         pos=read();
61         cnt++;cnt[v]=query(pos)+1;
62         cnt[sz]=1;cnt[rnd]=rand();
63         ins(root,cnt,pos);
64         printf("%d\\n",root[mx]);
65     }
66     return 0;
67 }
View Code

2.【SRM-07 D】天才麻将少女KPM

题意:Zsnuoの博客

分析:Zsnuoの博客

技术分享图片
  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<iostream>
  6 #define LL long long
  7 using namespace std;
  8 const int N=2e5+5;
  9 int n,L,R,a,tmp,cnt=1e5;
 10 int root,rt1,rt2,rt3,st[N],ch[N][9];
 11 #define lc ch][0
 12 #define rc ch][1
 13 #define rnd ch][2
 14 #define sz ch][3
 15 #define v ch][4
 16 #define tag ch][5
 17 #define mx ch][6
 18 #define mn ch][7
 19 #define cov ch][8
 20 int read()
 21 {
 22     int x=0,f=1;char c=getchar();
 23     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
 24     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
 25     return x*f;
 26 }
 27 void up(int w)
 28 {
 29     w[sz]=w[lc][sz]+w[rc][sz]+1;w[mx]=w[mn]=w[v];
 30     if(w[lc])w[mx]=max(w[mx],w[lc][mx]),w[mn]=min(w[mn],w[lc][mn]);
 31     if(w[rc])w[mx]=max(w[mx],w[rc][mx]),w[mn]=min(w[mn],w[rc][mn]);
 32 }
 33 void dn(int w)
 34 {
 35     if(w[cov])
 36     {
 37         w[lc][v]=w[lc][cov]=w[lc][mx]=w[lc][mn]=w[cov];
 38         w[rc][v]=w[rc][cov]=w[rc][mx]=w[rc][mn]=w[cov];
 39         w[lc][tag]=w[rc][tag]=0;
 40         w[cov]=0;
 41     }
 42     if(w[tag])
 43     {
 44         w[lc][v]+=w[tag];w[lc][tag]+=w[tag];
 45         w[lc][mx]+=w[tag];w[lc][mn]+=w[tag];
 46         w[rc][v]+=w[tag];w[rc][tag]+=w[tag];
 47         w[rc][mx]+=w[tag];w[rc][mn]+=w[tag];
 48         w[tag]=0;
 49     }
 50 }
 51 void dfs(int w){if(!w)return;dfs(w[lc]);dfs(w[rc]);up(w);}
 52 int build()
 53 {
 54     int top=0;
 55     for(int w=1;w<=1e5;w++)
 56     {
 57         w[rnd]=rand();
 58         while(top&&st[top][rnd]>w[rnd])
 59         {
 60             st[top][rc]=w[lc];
 61             w[lc]=st[top--];
 62         }
 63         st[top][rc]=w;st[++top]=w;
 64     }
 65     ch[0][1]=0;dfs(st[1]);
 66     return st[1];
 67 }
 68 void split(int w,int& l,int& r,int k)
 69 {
 70     if(!w){l=r=0;return;}
 71     dn(w);int lson=w[lc][sz];
 72     if(k<=lson){r=w;split(w[lc],l,w[lc],k);}
 73     else{l=w;split(w[rc],w[rc],r,k-lson-1);}
 74     up(w);
 75 }
 76 int merge(int a,int b)
 77 {
 78     if(!a||!b)return a+b;
 79     if(a[rnd]<b[rnd]){dn(a);a[rc]=merge(a[rc],b);up(a);return a;}
 80     else{dn(b);b[lc]=merge(a,b[lc]);up(b);return b;}
 81 }
 82 int rank(int w,int k)
 83 {
 84     if(!w)return 0;dn(w);
 85     int lson=w[lc][sz];
 86     if(k==lson+1)return w[v];
 87     if(k<=lson)return rank(w[lc],k);
 88     else return rank(w[rc],k-lson-1);
 89 }
 90 void ins(int& w,int x,int k)
 91 {
 92     dn(w);
 93     if(x[rnd]<w[rnd]||!w){split(w,x[lc],x[rc],k);w=x;up(w);return;}
 94     int lson=w[lc][sz];
 95     if(k<=lson)ins(w[lc],x,k);
 96     else ins(w[rc],x,k-lson-1);
 97     up(w);
 98 }
 99 void del(int& w,int k)
100 {
101     dn(w);
102     int lson=w[lc][sz];
103     if(k==lson+1){w=merge(w[lc],w[rc]);return;}
104     if(k<=lson)del(w[lc],k);
105     else del(w[rc],k-lson-1);
106     up(w);
107 }
108 void add(int L,int R,int V)
109 {
110     rt1=rt2=rt3=0;split(root,rt2,rt3,R);
111     root=rt2;rt2=0;split(root,rt1,rt2,L-1);
112     rt2[tag]+=V;rt2[v]+=V;rt2[mx]+=V;rt2[mn]+=V;
113     root=merge(rt1,rt2);root=merge(root,rt3);
114 }
115 void cover(int w,int V)
116 {
117     if(!w||w[mn]>=V)return;
118     dn(w);if(w[v]<V)w[v]=V;
119     if(w[mx]<=V){w[cov]=V;w[tag]=0;up(w);return;}
120     cover(w[lc],V);cover(w[rc],V);
121     up(w);
122 }
123 void update(int L,int R,int V)
124 {
125     rt1=rt2=rt3=0;split(root,rt2,rt3,R);
126     root=rt2;rt2=0;split(root,rt1,rt2,L-1);
127     cover(rt2,V);
128     root=merge(rt1,rt2);root=merge(root,rt3);
129 }
130 int main()
131 {
132     n=read();L=read();R=read();root=build();
133     for(int i=1;i<=n;i++)
134     {
135         a=read();
136         if(a>0)
137         {
138             tmp=rank(root,a-1)+1;
139             update(a,1e5,tmp);
140         }
141         else
142         {
143             del(root,R);cnt++;
144             tmp=rank(root,L-1);
145             cnt[v]=tmp;cnt[rnd]=rand();
146             ins(root,cnt,L-1);
147             add(L,R,1);tmp=rank(root,R);
148             if(R!=1e5)update(R+1,1e5,tmp);
149         }
150     }
151     printf("%d",root[mx]);
152     return 0;
153 }
View Code

3.【bzoj3786】星系探索

题意:见原题

分析:Zsnuoの博客

技术分享图片
  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #define LL long long
  6 using namespace std;
  7 const int N=2e5+10;
  8 int n,m,cnt,tmp,x,y,root,rt1,rt2,rt3;
  9 int st[N],q[N],first[N],ch[N][7];
 10 LL sh[N][3];
 11 char op[2];
 12 struct edge{int to,next;}e[N];
 13 #define lc ch][0
 14 #define rc ch][1
 15 #define rnd ch][2
 16 #define sz ch][3
 17 #define xi ch][4
 18 #define num ch][5
 19 #define fa ch][6
 20 #define v sh][0
 21 #define sum sh][1
 22 #define tag sh][2
 23 int read()
 24 {
 25     int x=0,f=1;char c=getchar();
 26     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
 27     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
 28     return x*f;
 29 }
 30 void ins(int from,int to){e[++cnt]=(edge){to,first[from]};first[from]=cnt;}
 31 void dfs(int x)
 32 {
 33     q[++cnt]=x;
 34     for(int i=first[x];i;i=e[i].next)dfs(e[i].to);
 35     q[++cnt]=x+n;
 36 }
 37 void up(int w)
 38 {
 39     int l=w[lc],r=w[rc];
 40     w[sz]=l[sz]+r[sz]+1;
 41     w[num]=l[num]+r[num]+w[xi];
 42     w[sum]=l[sum]+r[sum]+w[v];
 43 }
 44 void dn(int w)
 45 {
 46     int l=w[lc],r=w[rc];LL t=w[tag];
 47     if(!t)return;w[tag]=0;
 48     if(l)l[tag]+=t,l[v]+=t*l[xi],l[sum]+=t*l[num];
 49     if(r)r[tag]+=t,r[v]+=t*r[xi],r[sum]+=t*r[num];
 50 //    printf("l:%d xi:%d r:%d xi:%d\\n",l,l[xi],r,r[xi]);
 51 }
 52 void check(int w){if(!w)return;check(w[lc]);check(w[rc]);up(w);}
 53 int build(int n)
 54 {
 55     int top=0,w;
 56     for(int i=1;i<=n;i++)
 57     {
 58         w=q[i];w[rnd]=rand();
 59         while(top&&st[top][rnd]>w[rnd])
 60         {
 61             w[lc][fa]=st[top];st[top][rc]=w[lc];
 62             st[top][fa]=w;w[lc]=st[top--];
 63         }
 64         w[fa]=st[top];st[top][rc]=w;st[++top]=w;
 65     }
 66     ch[0][1]=0;st[1][fa]=0;check(st[1]);
 67     return st[1];
 68 }
 69 void split(int w,int& l,int fal,int& r,int far,int k)
 70 {
 71     if(!w){l=r=0;return;}
 72     dn(w);int lson=w[lc][sz];
 73     if(k<=lson)w[fa]=far,r=w,split(w[lc],l,fal,w[lc],w,k);
 74     else w[fa]=fal,l=w,split(w[rc],w[rc],w,r,far,k-lson-1);
 75     up(w);
 76 }
 77 int merge(int a,int b)
 78 {
 79     if(!a||!b)return a+b;
 80     if(a[rnd]<b[rnd]){dn(a);a[rc]=merge(a[rc],b);a[rc][fa]=a;up(a);return a;}
 81     else {dn(b);b[lc]=merge(a,b[lc]);b[lc][fa]=b;up(b);return b;}
 82 }
 83 int find(int x)
 84 {
 85     int ans=x[lc][sz]+1;
 86     while(x[fa])
 87     {
 88         if(x[fa][rc]==x)ans+=x[fa][lc][sz]+1;
 89         x=x[fa];
 90     }
 91     return ans;
 92 }
 93 void query()
 94 {
 95     x=read();rt1=rt2=0;split(root,rt1,0,rt2,0,find(x));
 96     printf("%lld\\n",rt1[sum]);root=merge(rt1,rt2);
 97 }
 98 void change()
 99 {
100     x=read();y=read();rt1=rt2=rt3=0;
101     split(root,rt1,0,rt3,0,find(x+n));
102     root=rt1;rt1=0;split(root,rt1,0,rt2,0,find(x)-1);
103     root=merge(rt1,rt3);rt1=rt3=0;
104     split(root,rt1,0,rt3,0,find(y));
105     root=merge(rt1,rt2);root=merge(root,rt3);
106 }
107 void add()
108 {
109     x=read();y=read();rt1=rt2=rt3=0;
110     split(root,rt1,0,rt3,0,find(x+n));
111     root=rt1;rt1=0;split(root,rt1,0,rt2,0,find(x)-1);
112     int w=rt2;w[tag]+=y;w[v]+=y*w[xi];w[sum]+=1ll*y*w[num];
113     root=merge(rt1,rt2);root=merge(root,rt3);
114 }
115 void print(int w,int dir)
116 {
117     if(!w)return;
118     if(dir==0)printf("from-left ");
119     if(dir==1)printf("from-right ");
120     printf("[%d] fa:%d v:%lld sum:%lld lson:%d rson:%d\\n",w,w[fa],w[v],w[sum],w[lc],w[rc]);
121     print(w[lc],0);print(w[rc],1);
122 }
123 int main()
124 {
125     n=read();
126     for(int i=2;i<=n;i++)tmp=read(),ins(tmp,i);
127     for(int i=1;i<=n;i++)tmp=read(),i[v]=tmp,(i+n)[v]=-tmp,i[xi]=1,(i+n)[xi]=-1;
128     cnt=0;dfs(1);root=build(n*2);m=read();//print(root,-1);
129     while(m--)
130     {
131         scanf("%s",op+1);
132         if(op[1]==Q)query();
133         else if(op[1]==C)change();
134         else add();
135 //        print(root,-1);
136     }
137     return 0;
138 }
View Code
技术分享图片
  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #define LL long long
  6 using namespace std;
  7 const int N=2e5+10;
  8 int n,m,cnt,tmp,x,y,root,rt1,rt2,rt3;
  9 int st[N],q[N],first[N],ch[N][7];
 10 LL sh[N][3];
 11 char op[2];
 12 struct edge{int to,next;}e[N];
 13 #define lc ch][0
 14 #define rc ch][1
 15 #define rnd ch][2
 16 #define sz ch][3
 17 #define xi ch][4
 18 #define num ch][5
 19 #define fa ch][6
 20 #define v sh][0
 21 #define sum sh][1
 22 #define tag sh][2
 23 int read()
 24 {
 25     int x=0,f=1;char c=getchar();
 26     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
 27     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
 28     return x*f;
 29 }
 30 void ins(int from,int to){e[++cnt]=(edge){to,first[from]};first[from]=cnt;}
 31 void dfs(int x)
 32 {
 33     q[++cnt]=x;
 34     for(int i=first[x];i;i=e[i].next)dfs(e[i].to);
 35     q[++cnt]=x+n;
 36 }
 37 void up(int w)
 38 {
 39     int l=w[lc],r=w[rc];
 40     w[sz]=l[sz]+r[sz]+1;
 41     w[num]=l[num]+r[num]+w[xi];
 42     w[sum]=l[sum]+r[sum]+w[v];
 43     if(l)l[fa]=w;if(r)r[fa]=w;
 44 }
 45 void dn(int w)
 46 {
 47     int l=w[lc],r=w[rc];LL t=w[tag];
 48     if(!t)return;w[tag]=0;
 49     if(l)l[tag]+=t,l[v]+=t*l[xi],l[sum]+=t*l[num];
 50     if(r)r[tag]+=t,r[v]+=t*r[xi],r[sum]+=t*r[num];
 51 }
 52 void check(int w){if(!w)return;check(w[lc]);check(w[rc]);up(w);}
 53 int build(int n)
 54 {
 55     int top=0,w;
 56     for(int i=1;i<=n;i++)
 57     {
 58         w=q[i];w[rnd]=rand();
 59         while(top&&st[top][rnd]>w[rnd])st[top][rc]=w[lc],w[lc]=st[top--];
 60         st[top][rc]=w;st[++top]=w;
 61     }
 62     ch[0][1]=0;st[1][fa]=0;check(st[1]);
 63     return st[1];
 64 }
 65 void split(int w,int& l,int fal,int& r,int far,int k)
 66 {
 67     if(!w){l=r=0;return;}
 68     dn(w);int lson=w[lc][sz];
 69     if(k<=lson)r=w,split(w[lc],l,fal,w[lc],w,k);
 70     else l=w,split(w[rc],w[rc],w,r,far,k-lson-1);
 71     up(w);
 72 }
 73 int merge(int a,int b)
 74 {
 75     if(!a||!b)return a+b;
 76     if(a[rnd]<b[rnd]){dn(a);a[rc]=merge(a[rc],b);up(a);return a;}
 77     else {dn(b);b[lc]=merge(a,b[lc]);up(b);return b;}
 78 }
 79 int find(int x)
 80 {
 81     int ans=x[lc][sz]+1;
 82     while(x[fa])
 83     {
 84         if(x[fa][rc]==x)ans+=x[fa][lc][sz]+1;
 85         x=x[fa];
 86     }
 87     return ans;
 88 }
 89 void query()
 90 {
 91     x=read();rt1=rt2=0;split(root,rt1,0,rt2,0,find(x));
 92     rt1[fa]=rt2[fa]=0;printf("%lld\\n",rt1[sum]);root=merge(rt1,rt2);root[fa]=0;
 93 }
 94 void change()
 95 {
 96     x=read();y=read();rt1=rt2=rt3=0;
 97     split(root,rt1,0,rt3,0,find(x+n));
 98     rt1[fa]=rt3[fa]=0;root=rt1;rt1=0;
 99     split(root,rt1,0,rt2,0,find(x)-1);
100     rt1[fa]=rt2[fa]=0;root=merge(rt1,rt3);rt1=rt3=0;
101     split(root,rt1,0,rt3,0,find(y));
102     root=merge(rt1,rt2);root=merge(root,rt3);root[fa]=0;
103 }
104 void add()
105 {
106     x=read();y=read();rt1=rt2=rt3=0;
107     split(root,rt1,0,rt3,0,find(x+n));
108     rt1[fa]=rt3[fa]=0;root=rt1;rt1=0;
109     split(root,rt1,0,rt2,0,find(x)-1);rt1[fa]=rt2[fa]=0;
110     int w=rt2;w[tag]+=y;w[v]+=y*w[xi];w[sum]+=1ll*y*w[num];
111     root=merge(rt1,rt2);root=merge(root,rt3);root[fa]=0;
112 }
113 int main()
114 {
115     n=read();
116     for(int i=2;i<=n;i++)tmp=read(),ins(tmp,i);
117     for(int i=1;i<=n;i++)tmp=read(),i[v]=tmp,(i+n)[v]=-tmp,i[xi]=1,(i+n)[xi]=-1;
118     cnt=0;dfs(1);
119     root=build(n*2);m=read();
120     while(m--)
121     {
122         scanf("%s",op+1);
123         if(op[1]==Q)query();
124         else if(op[1]==C)change();
125         else add();
126     }
127     return 0;
128 }
View Code

4.【bzoj1500】[NOI2005]维修数列

题意:见原题

分析:Zsnuoの博客

技术分享图片
  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<cstring>
  4 #include<cstdlib>
  5 using namespace std;
  6 const int N=5e5+5;
  7 const int inf=0x3f3f3f3f;
  8 int n,m,tot,pos,val,cnt,root,rt1,rt2,rt3;
  9 int st[N],id[N],a[N],ch[N][11];
 10 char op[15];
 11 #define lc ch][0
 12 #define rc ch][1
 13 #define rnd ch][2
 14 #define sz ch][3
 15 #define v ch][4
 16 #define tag ch][5
 17 #define rev ch][6
 18 #define sum ch][7
 19 #define mx ch][8
 20 #define lsum ch][9
 21 #define rsum ch][10
 22 int read()
 23 {
 24     int x=0,f=1;char c=getchar();
 25     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
 26     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
 27     return x*f;
 28 }
 29 int max(int a,int b){return a>b?a:b;}
 30 void up(int w)
 31 {
 32     int l=w[lc],r=w[rc];
 33     w[sz]=l[sz]+r[sz]+1;
 34     w[sum]=l[sum]+r[sum]+w[v];
 35     w[mx]=l[rsum]+w[v]+r[lsum];
 36     if(l)w[mx]=max(w[mx],l[mx]);
 37     if(r)w[mx]=max(w[mx],r[mx]);
 38     w[lsum]=max(l[lsum],l[sum]+w[v]+r[lsum]);
 39     w[rsum]=max(r[rsum],r[sum]+w[v]+l[rsum]);
 40 }
 41 void dn(int w)
 42 {
 43     int l=w[lc],r=w[rc];
 44     if(w[tag])
 45     {
 46         w[rev]=w[tag]=0;
 47         if(l)l[tag]=1,l[v]=w[v],l[sum]=w[v]*l[sz];
 48         if(r)r[tag]=1,r[v]=w[v],r[sum]=w[v]*r[sz];
 49         if(w[v]>=0)
 50         {
 51             if(l)l[mx]=l[lsum]=l[rsum]=l[sum];
 52             if(r)r[mx]=r[lsum]=r[rsum]=r[sum];
 53         }
 54         else
 55         {
 56             if(l)l[lsum]=l[rsum]=0,l[mx]=w[v];
 57             if(r)r[lsum]=r[rsum]=0,r[mx]=w[v];
 58         }
 59     }
 60     if(w[rev])
 61     {
 62         w[rev]^=1;l[rev]^=1;r[rev]^=1;
 63         swap(l[lsum],l[rsum]);swap(r[lsum],r[rsum]);
 64         swap(l[lc],l[rc]);swap(r[lc],r[rc]);
 65     }
 66 }
 67 void dfs(int w){if(!w)return;dfs(w[lc]);dfs(w[rc]);up(w);}
 68 int build(int n)
 69 {
 70     int top=0,w;
 71     for(int i=1;i<=n;i++)
 72     {
 73         w=id[cnt--];
 74         w[rnd]=rand();w[v]=a[i];
 75         while(top&&st[top][rnd]>w[rnd])
 76         {
 77             st[top][rc]=w[lc];
 78             w[lc]=st[top--];
 79         }
 80         st[top][rc]=w;
 81         st[++top]=w;
 82     }
 83     ch[0][1]=0;dfs(st[1]);
 84     return st[1];
 85 }
 86 void split(int w,int& l,int& r,int k)
 87 {
 88     if(!w){l=r=0;return;}
 89     dn(w);int lson=w[lc][sz];
 90     if(k<=lson){r=w;split(w[lc],l,w[lc],k);}
 91     else {l=w;split(w[rc],w[rc],r,k-lson-1);}
 92     up(w);
 93 }
 94 int merge(int a,int b)
 95 {
 96     if(!a||!b)return a+b;
 97     if(a[rnd]<b[rnd]){dn(a);a[rc]=merge(a[rc],b);up(a);return a;}
 98     else {dn(b);b[lc]=merge(a,b[lc]);up(b);return b;}
 99 }
100 void insert(int pos,int tot)
101 {
102     for(int i=1;i<=tot;i++)a[i]=read();
103     rt1=rt2=rt3=0;split(root,rt1,rt3,pos);
104     rt2=build(tot);
105     root=merge(rt1,rt2);root=merge(root,rt3);
106 }
107 void rec(int w)
108 {
109     if(!w)return;
110     int l=w[lc],r=w[rc];
111     rec(l);rec(r);id[++cnt]=w;
112     memset(ch[w],0,sizeof(ch[w]));
113 }
114 void erase(int pos,int tot)
115 {
116     rt1=rt2=rt3=0;split(root,rt2,rt3,pos+tot-1);
117     root=rt2;rt2=0;split(root,rt1,rt2,pos-1);
118     rec(rt2);root=merge(rt1,rt3);
119 }
120 void makesame(int pos,int tot,int val)
121 {
122     rt1=rt2=rt3=0;split(root,rt2,rt3,pos+tot-1);
123     root=rt2;rt2=0;split(root,rt1,rt2,pos-1);
124     int w=rt2;w[tag]=1;w[v]=val;w[sum]=val*w[sz];
125     if(val>=0)w[lsum]=w[rsum]=w[mx]=w[sum];
126     else w[lsum]=w[rsum]=0,w[mx]=val;
127     root=merge(rt1,rt2);root=merge(root,rt3);
128 }
129 void rever(int pos,int tot)
130 {
131     rt1=rt2=rt3=0;split(root,rt2,rt3,pos+tot-1);
132     root=rt2;rt2=0;split(root,rt1,rt2,pos-1);
133     int w=rt2;w[rev]^=1;swap(w[lc],w[rc]);swap(w[lsum],w[rsum]);
134     root=merge(rt1,rt2);root=merge(root,rt3);
135 }
136 void query(int pos,int tot)
137 {
138     rt1=rt2=rt3=0;split(root,rt2,rt3,pos+tot-1);
139     root=rt2;rt2=0;split(root,rt1,rt2,pos-1);
140     printf("%d\\n",rt2[sum]);root=merge(rt1,rt2);root=merge(root,rt3);
141 }
142 int main()
143 {
144     n=read();m=read();cnt=N-5;
145     for(int i=1;i<=N-5;i++)id[i]=i;
146     for(int i=1;i<=n;i++)a[i]=read();
147     root=build(n);
148     while(m--)
149     {
150         scanf("%s",op);
151         if(op[0]!=M||op[2]!=X)pos=read(),tot=read();
152         if(op[0]==I)insert(pos,tot);
153         else if(op[0]==D)erase(pos,tot);
154         else if(op[0]==M)
155         {
156             if(op[2]==X)printf("%d\\n",root[mx]);
157             else val=read(),makesame(pos,tot,val);
158         }
159         else if(op[0]==R)rever(pos,tot);
160         else query(pos,tot);
161     }
162     return 0;
163 }
View Code

【CDQ分治】

〖相关资料

《从《Cash》谈一类分治算法的应用》

〖相关题目

1.【bzoj1492】[NOI2007]货币兑换Cash

题意:见原题

分析:见资料

技术分享图片
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5 using namespace std;
 6 const int N=1e5+5;
 7 const double eps=1e-9;
 8 int n,s[N];
 9 double f[N];
10 struct node{double x,y,a,b,k,rate;int id;}t[N],tmp[N];
11 bool cmp(node a,node b){return a.k>b.k;}
12 double get(int a,int b)
13 {
14     if(!b)return -1e30;
15     if(fabs(t[a].x-t[b].x)<eps)return 1e30;
16     return (t[b].y-t[a].y)/(t[b].x-t[a].x);
17 }
18 void cdq(int l,int r)
19 {
20     if(l==r)
21     {
22         f[l]=max(f[l],f[l-1]);
23         t[l].y=f[l]/(t[l].a*t[l].rate+t[l].b);
24         t[l].x=t[l].y*t[l].rate;
25         return;
26     }
27     int mid=(l+r)>>1,h1=l,h2=mid+1;
28     for(int i=l;i<=r;i++)
29         if(t[i].id<=mid)tmp[h1++]=t[i];
30         else tmp[h2++]=t[i];
31     for(int i=l;i<=r;i++)t[i]=tmp[i];
32     cdq(l,mid);int top=0,now=1;
33     for(int i=l;i<=mid;i++)
34     {
35         while(top>1&&get(s[top-1],s[top])<get(s[top],i)+eps)top--;
36         s[++top]=i;
37     }
38     s[++top]=0;
39     for(int i=mid+1;i<=r;i++)
40     {
41         while(get(s[now],s[now+1])+eps>t[i].k)now++;
42         f[t[i].id]=max(f[t[i].id],t[s[now]].x*t[i].a+t[s[now]].y*t[i].b);
43     }
44     cdq(mid+1,r);h1=l;h2=mid+1;
45     for(int i=l;i<=r;i++)
46     {
47         if(h1>mid){tmp[i]=t[h2++];continue;}
48         if(h2>r){tmp[i]=t[h1++];continue;}
49         if(t[h1].x<t[h2].x||(fabs(t[h1].x-t[h2].x)<eps&&t[h1].y<t[h2].y))tmp[i]=t[h1++];
50         else tmp[i]=t[h2++];
51     }
52     for(int i=l;i<=r;i++)t[i]=tmp[i];
53 }
54 int main()
55 {
56     scanf("%d%lf",&n,&f[0]);
57     for(int i=1;i<=n;i++)
58     {
59         scanf("%lf%lf%lf",&t[i].a,&t[i].b,&t[i].rate);
60         t[i].k=-t[i].a/t[i].b;t[i].id=i;
61     }
62     sort(t+1,t+n+1,cmp);cdq(1,n);
63     printf("%.3lf",f[n]);
64     return 0;
65 }
View Code

【整体二分】

〖相关题目

1.【bzoj1901】Zju2112 Dynamic Rankings

题意:给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]……a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。

分析:带修改的整体二分

技术分享图片
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #define LL long long
 5 using namespace std;
 6 const int N=5e4+5;
 7 const int inf=1e9;
 8 int n,m,cnt,qid,id,temp,x[N],ans[N],tr[N];
 9 bool f[N];
10 char ch[5];
11 struct node{int op,l,r,k,num;}a[N],tmp[N];
12 int lowbit(int x){return x&(-x);}
13 void insert(int x,int c){while(x<=n)tr[x]+=c,x+=lowbit(x);}
14 int query(int x){int ans=0;while(x)ans+=tr[x],x-=lowbit(x);return ans;}
15 int read()
16 {
17     int x=0,f=1;char c=getchar();
18     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
19     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
20     return x*f;
21 }
22 void work(int ql,int qr,int L,int R)
23 {
24     if(ql>qr||L>R)return;
25     if(L==R){for(int i=ql;i<=qr;i++)if(a[i].op)ans[a[i].num]=L;return;}
26     int mid=(L+R)>>1,h1=ql,h2=ql;
27     for(int i=ql;i<=qr;i++)
28         if(a[i].op)
29         {
30             temp=query(a[i].r)-query(a[i].l-1);
31             if(temp>=a[i].k)f[i]=true,h2++;
32             else f[i]=false,a[i].k-=temp;
33         }
34         else
35         {
36             if(a[i].num<=mid)f[i]=true,h2++,insert(a[i].l,a[i].k);
37             else f[i]=false;
38         }
39     for(int i=ql;i<=qr;i++)if((!a[i].op)&&f[i])insert(a[i].l,-a[i].k);
40     for(int i=ql;i<=qr;i++)
41         if(f[i])tmp[h1++]=a[i];
42         else tmp[h2++]=a[i];
43     for(int i=ql;i<=qr;i++)a[i]=tmp[i];
44     work(ql,h1-1,L,mid);work(h1,qr,mid+1,R);
45 }
46 int main()
47 {
48     n=read();m=read();
49     for(int i=1;i<=n;i++)x[i]=read(),a[++cnt]=(node){0,i,0,1,x[i]};
50     for(int i=1;i<=m;i++)
51     {
52         scanf("%s",ch+1);
53         if(ch[1]==Q)
54         {
55             a[++cnt].op=1;a[cnt].num=++qid;
56             a[cnt].l=read();a[cnt].r=read();a[cnt].k=read();
57         }
58         else
59         {
60             id=read();temp=read();
61             a[++cnt]=(node){0,id,0,-1,x[id]};
62             a[++cnt]=(node){0,id,0,1,x[id]=temp};
63         }
64     }
65     work(1,cnt,-inf,inf);
66     for(int i=1;i<=qid;i++)printf("%d\\n",ans[i]);
67     return 0;
68 }
View Code

2.【bzoj2527】[Poi2011]Meteors

题意:见原题

分析:Zsnuoの博客 

技术分享图片
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<vector>
 5 #define LL long long
 6 using namespace std;
 7 const int N=3e5+5;
 8 const int inf=0x3f3f3f3f;
 9 int n,m,K,now,op;
10 int num[N],Li[N],Ri[N],Ai[N],id[N],tmp[N],ans[N];
11 LL sum,tr[N];
12 bool f[N];
13 vector<int> nation[N];
14 int read()
15 {
16     int x=0,f=1;char c=getchar();
17     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
18     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
19     return x*f;
20 }
21 int lowbit(int x){return x&(-x);}
22 void add(int x,LL c){while(x<=m)tr[x]+=c,x+=lowbit(x);}
23 LL query(int x){LL ans=0;while(x)ans+=tr[x],x-=lowbit(x);return ans;}
24 void update(int id,int f)
25 {
26     if(Li[id]<=Ri[id])add(Li[id],Ai[id]*f),add(Ri[id]+1,-Ai[id]*f);
27     else add(1,Ai[id]*f),add(Ri[id]+1,-Ai[id]*f),add(Li[id],Ai[id]*f);
28 }
29 void work(int ql,int qr,int L,int R)
30 {
31     if(ql>qr)return;
32     if(L==R){for(int i=ql;i<=qr;i++)ans[id[i]]=L;return;}
33     int h1=ql,h2=ql,mid=(L+R)>>1;
34     while(op<mid)op++,update(op,1);
35     while(op>mid)update(op,-1),op--;
36     for(int i=ql;i<=qr;i++)
37     {
38         sum=0;now=id[i];
39         for(int j=0;j<nation[now].size();j++)
40         {
41             sum+=query(nation[now][j]);
42             if(sum>=num[now])break;
43         }
44         if(sum>=num[now])f[now]=true,h2++;
45         else f[now]=false;
46     }
47     for(int i=ql;i<=qr;i++)
48         if(f[id[i]])tmp[h1++]=id[i];
49         else tmp[h2++]=id[i];
50     for(int i=ql;i<=qr;i++)id[i]=tmp[i];
51     work(ql,h1-1,L,mid);work(h1,qr,mid+1,R);
52 }
53 int main()
54 {
55     n=read();m=read();
56     for(int i=1;i<=m;i++)now=read(),nation[now].push_back(i);
57     for(int i=1;i<=n;i++)num[i]=read(),id[i]=i;
58     K=read();K++;Li[K]=1;Ri[K]=m;Ai[K]=inf;
59     for(int i=1;i<K;i++)Li[i]=read(),Ri[i]=read(),Ai[i]=read();
60     work(1,n,1,K);
61     for(int i=1;i<=n;i++)
62         if(ans[i]==K)printf("NIE\\n");
63         else printf("%d\\n",ans[i]);
64     return 0;
65 }
View Code

3.【bzoj3110】[Zjoi2013]K大数查询

题意:有N个位置,M个操作。操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c。如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少。

分析:整体二分裸题

技术分享图片
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #define LL long long
 6 using namespace std;
 7 const int N=1e5+5;
 8 int n,m,qid,mx,ans[N];
 9 LL tr[N][2];
10 bool f[N];
11 struct node{int op,l,r,c,id;}a[N],tmp[N];
12 LL read()
13 {
14     LL x=0,f=1;char c=getchar();
15     while(c<0||c>9){if(c==-)f=-1;c=getchar();}
16     while(c>=0&&c<=9){x=x*10+c-0;c=getchar();}
17     return x*f;
18 }
19 int lowbit(int x){return x&(-x);}
20 void add(int x,LL c,int id){while(x<=n)tr[x][id]+=c,x+=lowbit(x);}
21 void insert(int id,LL c){add(id,c,0);add(id,c*id,1);}
22 LL query(int x,int id){LL ans=0;while(x)ans+=tr[x][id],x-=lowbit(x);return ans;}
23 LL ask(int id){LL ans=(id+1)*query(id,0)-query(id,1);return ans;}
24 void work(int x,int y,int l,int r)
25 {
26     if(l==r){for(int i=x;i<=y;i++)if(a[i].op==2)ans[a[i].id]=l;return;}
27     int h1=x,h2=x,mid=(l+r)>>1;
28     for(int i=x;i<=y;i++)
29         if(a[i].op==2)
30         {
31             LL temp=ask(a[i].r)-ask(a[i].l-1);
32             if(temp<a[i].c)f[i]=false,a[i].c-=temp;
33             else f[i]=true,h2++;
34         }
35         else if(a[i].c<=mid)insert(a[i].l,1),insert(a[i].r+1,-1),f[i]=true,h2++;
36         else f[i]=false;
37     for(int i=x;i<=y;i++)if(a[i].op==1&&a[i].c<=mid)insert(a[i].l,-1),insert(a[i].r+1,1);
38     for(int i=x;i<=y;i++)if(f[i])tmp[h1++]=a[i];else tmp[h2++]=a[i];
39     for(int i=x;i<=y;i++)a[i]=tmp[i];
40     work(x,h1-1,l,mid);work(h1,y,mid+1,r);
41 }
42 int main()
43 {
44     n=read();m=read();
45     for(int i=1;i<=m;i++)
46     {
47         a[i].op=read();a[i].l=read();a[i].r=read();a[i].c=read();
48         if(a[i].op==1)a[i].c=n-a[i].c+1,mx=max(mx,a[i].c);
49         else a[i].id=++qid;
50     }
51     work(1,m,1,mx);
52     for(int i=1;i<=qid;i++)printf("%d\\n",n-ans[i]+1);
53     return 0;
54 }
View Code

 

以上是关于算法总结数据结构的主要内容,如果未能解决你的问题,请参考以下文章

python常用代码片段总结

有人可以解释啥是 SVN 平分算法吗?理论上和通过代码片段[重复]

常用编程思想与算法

片段(Java) | 机试题+算法思路+考点+代码解析 2023

BootStrap有用代码片段(持续总结)

BootStrap实用代码片段(持续总结)