算法总结数据结构
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 }
〖相关题目〗
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 }
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 }
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 }
【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 }
【线段树】
〖模板代码〗
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 }
〖相关题目〗
题意: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 }
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 }
【树状数组】
〖模板代码〗
[单点修改区间查询]
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;}
[区间修改区间查询]
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 }
〖相关题目〗
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 }
【堆】
〖模板代码〗
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 }
【主席树】
〖相关题目〗
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 }
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 }
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 }
【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 }
[线性建树、区间加、区间翻转、区间查询]
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 }
[查询历史版本]
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 }
〖相关题目〗
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 }
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 }
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 }
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 }
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 }
【CDQ分治】
〖相关资料〗
〖相关题目〗
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 }
【整体二分】
〖相关题目〗
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 }
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 }
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 }
以上是关于算法总结数据结构的主要内容,如果未能解决你的问题,请参考以下文章
有人可以解释啥是 SVN 平分算法吗?理论上和通过代码片段[重复]