1 //1.主席树模板练习--HDU2665 Kth number 2 //0.0 3 #include<iostream> 4 #include<algorithm> 5 #include<vector> 6 #include<cstdio> 7 #include<cstdlib> 8 #include<cmath> 9 #include<cstring> 10 using namespace std; 11 struct tree{ 12 int val,l,r; 13 }t[2000000]; 14 int tot,a[100000],n,m,u[100000],root[100000]; 15 int build_tree(int l,int r) 16 { 17 int now=tot++; 18 t[now].val=0; 19 if (l!=r) 20 { 21 int m=(l+r)>>1; 22 t[now].l=build_tree(l,m); 23 t[now].r=build_tree(m+1,r); 24 } 25 return now; 26 } 27 int next(int last,int l,int r,int rank) 28 { 29 int now=tot++; 30 t[now]=t[last]; 31 t[now].val++; 32 if (l!=r) 33 { 34 int m=(l+r)>>1; 35 if (rank<=m) t[now].l=next(t[last].l,l,m,rank); 36 else t[now].r=next(t[last].r,m+1,r,rank); 37 } 38 return now; 39 } 40 int scr(int up,int down,int l,int r,int k) 41 { 42 if (l==r) return l; 43 int m=(l+r)>>1; 44 int lnum=t[t[up].l].val-t[t[down].l].val; 45 if (k<=lnum) return scr(t[up].l,t[down].l,l,m,k); 46 else return scr(t[up].r,t[down].r,m+1,r,k-lnum); 47 } 48 int main() 49 { 50 freopen("in.in","r",stdin); freopen("out.out","w",stdout); 51 int T; 52 cin>>T; 53 while (T--) 54 { 55 cin>>n>>m; 56 for (int i=0;i<n;i++) {cin>>a[i]; u[i]=a[i];} 57 sort(u,u+n); 58 int len=unique(u,u+n)-u; 59 tot=0; root[0]=build_tree(1,len); 60 for (int i=0;i<n;i++) 61 { 62 int rank=lower_bound(u,u+len,a[i])-u+1; 63 root[i+1]=next(root[i],1,len,rank); 64 } 65 while (m--) 66 { 67 int l,r,k; 68 cin>>l>>r>>k; 69 cout<<u[scr(root[r],root[l-1],1,len,k)-1]<<endl; 70 } 71 } 72 return 0; 73 }
2.线段树
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #define llg long long 8 #define maxn 200000*3+10 9 using namespace std; 10 11 llg i,j,ans,k,x,n,m,sum[maxn],set[maxn],addv[maxn],type,y,v,bj[maxn]/*是否具有set标记*/; 12 13 void build(llg o,llg l,llg r) 14 { 15 if (l==r) 16 { 17 scanf("%lld",&sum[o]); 18 } 19 else{ 20 llg mid=(l+r)/2; 21 build(o*2,l,mid); 22 build(o*2+1,mid+1,r); 23 sum[o]=sum[o*2]+sum[o*2+1]; 24 } 25 } 26 27 void pushdown(llg o,llg l,llg r) 28 { 29 llg lc=o*2,rc=o*2+1,mid=(r+l)/2; 30 if (bj[o]) 31 { 32 bj[o]=0; bj[lc]=bj[rc]=1; 33 set[lc]=set[rc]=set[o]; 34 sum[lc]=set[o]*(mid-l+1); 35 sum[rc]=set[o]*(r-mid); 36 addv[lc]=addv[rc]=0; 37 } 38 if (addv[o]) 39 { 40 addv[lc]+=addv[o]; addv[rc]+=addv[o]; 41 sum[lc]+=addv[o]*(mid-l+1); 42 sum[rc]+=addv[o]*(r-mid);addv[o]=0; 43 } 44 } 45 46 void add(llg o,llg l,llg r) 47 { 48 pushdown(o,l,r); 49 if (l>=x && r<=y) 50 { 51 addv[o]+=v; sum[o]+=(r-l+1)*v; 52 return ; 53 } 54 llg lc=o*2,rc=o*2+1,mid=(r+l)/2; 55 if (x<=mid) add(lc,l,mid); 56 if (y>mid) add(rc,mid+1,r); 57 sum[o]=sum[lc]+sum[rc]; 58 } 59 60 void sum_(llg o,llg l,llg r) 61 { 62 pushdown(o,l,r); 63 if (l>=x && r<=y) 64 { 65 ans+=sum[o]; 66 return ; 67 } 68 llg lc=o<<1,rc=o<<1|1,mid=(r+l)>>1; 69 if (x<=mid) sum_(lc,l,mid); 70 if (y>mid) sum_(rc,mid+1,r); 71 } 72 void seet(llg o,llg l,llg r) 73 { 74 75 } 76 int main() 77 { 78 freopen("in.in","r",stdin); freopen("out.out","w",stdout); 79 cin>>n; 80 build(1,1,n); 81 cin>>m; 82 while (m--) 83 { 84 scanf("%lld",&type); 85 if (type==1)//add 86 { 87 scanf("%lld%lld%lld",&x,&y,&v); 88 add(1,1,n); 89 } 90 if (type==3)//set 91 { 92 scanf("%lld%lld%lld",&x,&y,&v); 93 seet(1,1,n); 94 } 95 if (type==2)//sum 96 { 97 ans=0; 98 scanf("%lld%lld",&x,&y); 99 sum_(1,1,n); 100 printf("%lld ",ans); 101 } 102 } 103 return 0; 104 }
3.spaly
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cmath> 6 #include<cstring> 7 #define ll long long 8 #define maxn 100010 9 ll father[maxn],rightson[maxn],leftson[maxn],root; 10 using namespace std; 11 void right_rotate(ll x)//右旋 12 { 13 ll y=father[x],z=father[y]; 14 leftson[y]=rightson[x]; 15 if (rightson[x]!=0) father[rightson[x]]=y;//处理x的右子树 16 father[x]=z; 17 if (z!=0) 18 { 19 if (leftson[z]==y) leftson[z]=x;else rightson[z]=x; 20 } 21 rightson[x]=y; father[y]=x; 22 } 23 /* 24 右旋只需要三步: 25 1.将X的右子树B(如果有的话)作为Y的左子树,同时让B认Y作爹 26 2.设Z为原本Y结点的父亲,让X认Z做爹(如果Z存在的话),将X作为Z的儿子(是左是右得由Y是Z的左儿子还是右儿子决定,要左右一致) 27 3.将Y作为X的右子树,同时让Y认X作爹 28 */ 29 void left_rotate(ll x) 30 { 31 ll y=father[x],z=father[y]; 32 rightson[y]=leftson[x]; 33 if(leftson[x]!=0)father[leftson[x]]=y; 34 father[x]=z; 35 if(z!=0) 36 { 37 if(leftson[z]==y)leftson[z]=x;else rightson[z]=x; 38 } 39 leftson[x]=y;father[y]=x; 40 } 41 void splay(ll x,ll llg)//表示将x不停向上旋转,知道X成为结点为llg的子树 42 { 43 while(father[x]!=llg) 44 { 45 long y=father[x];long z=father[y]; 46 if(z==llg) 47 { 48 if(rightson[y]==x)left_rotate(x);else right_rotate(x); 49 } 50 else 51 { 52 if(rightson[z]==y && rightson[y]==x){left_rotate(y); left_rotate(x);} 53 else if(rightson[z]==y && leftson[y]==x) {right_rotate(x); left_rotate(x);} 54 else if(leftson[z]==y && leftson[y]==x) {right_rotate(y); right_rotate(x);} 55 else {left_rotate(x); right_rotate(x);} 56 } 57 } 58 if(llg==0) root=x; 59 } 60 ll findleft(ll x)//找这个节点左子树的最大值(前驱) 61 { 62 ll left=leftson[x]; 63 while (rightson[left]!=0) left=rightson[left]; 64 return left; 65 } 66 ll findright(ll x)//找这个节点在右子树的最小值(后继) 67 { 68 ll right=rightson[x]; 69 while (leftson[right]!=0) right=leftson[right]; 70 return right; 71 } 72 int main() 73 { 74 return 0; 75 }
4.并查集
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<vector> 7 #define yyj(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout); 8 #define llg long long 9 using namespace std; 10 llg i,j,k,n,m,dad[200100],x,y; 11 llg find (llg x) 12 { 13 return dad[x]==x?x:dad[x]=find(dad[x]); 14 } 15 int main() 16 { 17 yyj("a"); 18 cin>>n; 19 for (i=1;i<=n;i++) dad[i]=i; 20 cin>>m; 21 while (m--) 22 { 23 cin>>x>>y; 24 if (find(x)!=find(y)) dad[find(y)]=find(x); 25 } 26 cin>>m; 27 while (m--) 28 { 29 cin>>x>>y; 30 if (find(x)!=find(y)) cout<<"NO"<<endl;else cout<<"YES"<<endl; 31 } 32 return 0; 33 }
5.树状数组
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<vector> 7 #define yyj(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout); 8 #define llg long long 9 using namespace std; 10 llg a[1000],i,j,k,n,m,c[1000],y,x,type; 11 llg lowbit(llg x) 12 { 13 return x&-x; 14 } 15 void add(llg w,llg v) 16 { 17 while (w<=n) 18 { 19 c[w]+=v; w+=lowbit(w); 20 } 21 } 22 llg sum(llg w) 23 { 24 llg ans=0; 25 while (w>0) 26 { 27 ans+=c[w]; w-=lowbit(w); 28 } 29 return ans; 30 } 31 int main() 32 { 33 yyj("a"); 34 cin>>n; 35 for (i=1;i<=n;i++) 36 { 37 cin>>a[i]; 38 add(i,a[i]); 39 } 40 cin>>m; 41 while (m--) 42 { 43 cin>>type; 44 if (type==1) 45 { 46 cin>>x>>y; 47 add(x,y); 48 } 49 if (type==2) 50 { 51 cin>>x>>y; 52 cout<<sum(y)-sum(x-1)<<endl; 53 } 54 } 55 return 0; 56 }