数据结构这种东西敲起来十分爽
数据结构往往替代了我们思考的过程,但还是比较好用的
虽然STL已经内置了很多数据结构,但是NOIP不开O2。。。。。
所以很慢很慢很慢。。。。。nlogn会变成n^2,。。。。所以还是自己写吧
从最基本的开始
队列(队列是一种先进先出的数据结构)
//加入操作 inline void push_up(int x){ q[++tail]=x; } //取队列最前端的元素 inline int top(){ return q[head]; } //删除队列最前面的元素并返回元素 inline void pop(){ return q[head++]; } //判断队列是否为空 inline bool empty(){ if(head<=tail) return true; else return false; }
栈(栈与队列不同,废话名字都不一样,栈是维护先进后出的一种数据结构)
//加入操作 inline void push_up(int x){ q[++top]=x; } //取栈最顶端的元素 inline int top(){ return q[top]; } //删除栈最前面的元素并返回元素 inline void pop(){ return q[--top]; }
有关树的结构
树状数组(树状数组是维护动态区间和的一个极有利的数据结构)
inline lowbit(int x){ return x&-x; } inline void insert(int x){ while(x<MAXN){ c[x]+=v; x+=lowbit(x); } } inline long long search(int x){ long long sum; while(x){ sum+=c[x]; x-=lowbit(x); } return sum; }
平衡树(Treep版本)
void update(int &root) {T[root].siz=T[T[root].leftt].siz+T[T[root].rightt].siz+T[root].weight;} void left_rote(int &root){ int tmp=T[root].rightt;T[root].rightt=T[tmp].leftt;T[tmp].leftt=root; T[tmp].siz=T[root].siz;update(root);root=tmp; } void right_rote(int &root){ int tmp=T[root].leftt;T[root].leftt=T[tmp].rightt;T[tmp].rightt=root; T[tmp].siz=T[root].siz;update(root);root=tmp; } void insert(int &root,int x){ if(root==0) {tol++;root=tol;T[root].siz=T[root].weight=1;T[root].v=x;T[root].have=rand();return;} T[root].siz++; if(T[root].v==x) {T[root].weight++;return;} if(x>T[root].v){ insert(T[root].rightt,x); if(T[root].have<T[T[root].rightt].have) left_rote(root); } else{ insert(T[root].leftt,x); if(T[T[root].leftt].have>T[root].have) right_rote(root); } } void delte(int &root,int x){ if(root==0) return; if(x==T[root].v){ if(T[root].weight>1) {T[root].weight--;T[root].siz--;return;} else{ if(T[root].leftt*T[root].rightt==0) root=T[root].leftt+T[root].rightt; else{ if(T[T[root].leftt].have<T[T[root].rightt].have) {right_rote(root);delte(root,x);} else {left_rote(root);delte(root,x);} } } } T[root].siz--; if(x<T[root].v) delte(T[root].leftt,x); else delte(T[root].rightt,x); } void nxt(int root,int x){ if(root==0) return; if(T[root].v>=x) {tmp=T[root].v;nxt(T[root].leftt,x);} else nxt(T[root].rightt,x); }
平衡树(Splay版本)
#include <bits/stdc++.h> #define inf 10000010 #define ll long long using namespace std; inline int read(){ int x=0;int f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } const int MAXN=1e6+10; namespace Splay{ struct splaytree{ int son[2],siz,delta,v,fa,id,rev,key,maxn; }T[MAXN]; int tot,root,n,m,sz=0; inline void update(int x){ if(x){ T[x].siz=1; if(T[x].son[0]) T[x].siz+=T[T[x].son[0]].siz; if(T[x].son[1]) T[x].siz+=T[T[x].son[1]].siz; T[x].maxn=T[x].v; if(T[x].son[1]) T[x].maxn=max(T[x].maxn,T[T[x].son[1]].maxn); if(T[x].son[0]) T[x].maxn=max(T[x].maxn,T[T[x].son[0]].maxn); } } inline void push_up(int x){ if(T[x].delta!=0){ T[T[x].son[0]].delta+=T[x].delta;T[T[x].son[1]].delta+=T[x].delta; T[T[x].son[0]].v+=T[x].delta;T[T[x].son[1]].v+=T[x].delta; T[T[x].son[0]].maxn+=T[x].delta;T[T[x].son[1]].maxn+=T[x].delta; T[x].delta=0; } if(T[x].rev){ swap(T[x].son[0],T[x].son[1]); T[T[x].son[1]].rev^=T[x].rev; T[T[x].son[0]].rev^=T[x].rev; T[x].rev=0; } } inline int getfather(int x){ return x==T[T[x].fa].son[1]; } inline void rota(int x){ int oldl=T[x].fa;int oldf=T[oldl].fa;int wei=getfather(x); T[oldl].son[wei]=T[x].son[wei^1];T[T[x].son[wei^1]].fa=oldl; T[x].son[wei^1]=oldl;T[oldl].fa=x;T[x].fa=oldf; if(oldf){ T[oldf].son[oldl==T[oldf].son[1]]=x; } update(oldl);update(x); } inline void splay(int x,int tal){ for(int fa;(fa=T[x].fa)!=tal;rota(x)){ if(T[fa].fa!=tal){ rota(getfather(x)==getfather(fa)?fa:x); } } if(tal==0) root=x; } inline int find(int x){ int now=root; while(1){ push_up(now); if(x<=T[T[now].son[0]].siz){ now=T[now].son[0]; } else{ x-=T[T[now].son[0]].siz+1; if(x==0) return now; now=T[now].son[1]; } } } inline int build(int leftt,int rightt,int root){ if(leftt>rightt) return 0; int mid=(leftt+rightt)>>1; int now=++sz; T[now].fa=root; T[now].id=mid;T[now].delta=0;T[now].v=0;T[now].rev=0;T[now].delta=0;T[now].maxn=0; int lefttchild=build(leftt,mid-1,now); int righttchild=build(mid+1,rightt,now); T[now].son[0]=lefttchild;T[now].son[1]=righttchild; update(now); return now; } inline void insert(int leftt,int rightt,int vv){ leftt=find(leftt);rightt=find(rightt+2); splay(leftt,0);splay(rightt,leftt); int now=T[rightt].son[0]; T[now].delta+=vv; T[now].v+=vv;T[now].maxn+=vv; } inline void getmax(int leftt,int rightt){ leftt=find(leftt);rightt=find(rightt+2); splay(leftt,0);splay(rightt,leftt); int now=T[rightt].son[0]; printf("%d ",T[now].maxn); } inline void reserve(int leftt,int rightt){ if(leftt>=rightt) return; leftt=find(leftt);rightt=find(rightt+2); splay(leftt,0);splay(rightt,leftt); int now=T[rightt].son[0]; T[now].rev^=1; } inline void print(){ for(int i=1;i<=n+2;i++){ cout<<T[i].fa<<' '<<T[i].v<<' '<<T[i].id<<' '<<T[i].maxn<<endl; } } void init(){ n=read();m=read(); root=build(1,n+2,0); } void solve(){ while(m--){ int vv=read(); if(vv==1){ int leftt=read();int rightt=read();int vv=read(); insert(leftt,rightt,vv); } if(vv==2){ int leftt=read();int rightt=read(); reserve(leftt,rightt); } if(vv==3){ int leftt=read();int rightt=read(); getmax(leftt,rightt); } } } } int main(){ //freopen("All.in","r",stdin); //freopen("a.out","w",stdout); using namespace Splay; init(); solve(); return 0; }
线段树(单点修改)
void buildtree(int left,int right,int root) { if(yy<left||yy>right) return; if(left==right) {tree[root].maxn=vv;return;} int mid=(left+right)/2; buildtree(left,mid,root*2); buildtree(mid+1,right,root*2+1); tree[root].maxn=max(tree[root*2].maxn,tree[root*2+1].maxn); } int searchtree(int left,int right,int root) { int mid,templ,tempr; if(yy>right||vv<left) return -20000000; if(yy<=left&&vv>=right) return tree[root].maxn; mid=(right+left)/2; templ=searchtree(left,mid,root*2); tempr=searchtree(mid+1,right,root*2+1); return max(templ,tempr); } View Code
线段树(区间修改)
void buildtree(int left,int right,int root) { if(x>right||y<left) return; if(x<=left&&y>=right) { tree[root].delta++; tree[root].maxx++; return; } int mid=(left+right)/2; int delta=tree[root].delta; tree[root*2].delta+=delta;tree[root*2].maxx+=delta; tree[root*2+1].delta+=delta;tree[root*2+1].maxx+=delta; tree[root].delta=0; buildtree(left,mid,root*2); buildtree(mid+1,right,root*2+1); tree[root].maxx=max(tree[root*2].maxx,tree[root*2+1].maxx); } int searchtree(int left,int right,int root) { if(y<left||x>right) return -2000000; if(x<=left&&y>=right) return tree[root].maxx; int mid=(left+right)/2; int delta=tree[root].delta; tree[root*2].delta+=delta;tree[root*2].maxx+=delta; tree[root*2+1].delta+=delta;tree[root*2+1].maxx+=delta; tree[root].delta=0; int templ=searchtree(left,mid,root*2); int tempr=searchtree(mid+1,right,root*2+1); return max(templ,tempr); }
树链剖分
void dfs1(int father,int node,int depth){ siz[node]=1;fa[node]=father;dep[node]=depth;son[node]=0;int maxxn=0; for(int i=linkk[node];i;i=e[i].next){ if(e[i].y!=father){ dfs1(node,e[i].y,depth+1); if(siz[e[i].y]>maxxn) son[node]=e[i].y,maxxn=siz[e[i].y]; siz[node]+=siz[e[i].y]; } } //cout<<siz[node]<<endl; } void dfs2(int node,int id){ cnt[node]=++tot;Node[tot]=node;top[node]=id; if(son[node]) dfs2(son[node],id); for(int i=linkk[node];i;i=e[i].next){ if(e[i].y!=fa[node]&&e[i].y!=son[node]) dfs2(e[i].y,e[i].y); } } void buildtree(int l,int r,int root){ if(l==r) {T[root].sum=1;if(l==1) T[root].sum=0;return;} int mid=(l+r)>>1; buildtree(l,mid,root<<1); buildtree(mid+1,r,root<<1|1); T[root].sum=T[root<<1].sum+T[root<<1|1].sum; } void insertt(int l,int r,int root){ if(l>x||r<x) return; if(l==r) {T[root].sum=0;return;} int mid=(l+r)>>1; insertt(l,mid,root<<1); insertt(mid+1,r,root<<1|1); T[root].sum=T[root<<1].sum+T[root<<1|1].sum; } int find(int l,int r,int root){ if(l>=x&&r<=y) return T[root].sum; if(l>y||r<x) return 0; int mid=(r+l)>>1; return find(l,mid,root<<1)+find(mid+1,r,root<<1|1); } void init(){ n=read(); for(int i=1;i<n;i++){ int xx=read();int yy=read(); insert(xx,yy); insert(yy,xx); } dfs1(0,1,0); dfs2(1,1); buildtree(1,n,1); } int search(int node){ if(node==1) return 0; int ans=0; while(top[node]!=1){ x=cnt[top[node]]; y=cnt[node]; ans+=find(1,n,1); node=fa[top[node]]; } if(node==1) return ans; y=cnt[node]; x=cnt[top[node]]; ans+=find(1,n,1); return ans; }
主席树(不带修改的区间第k大)
#include <bits/stdc++.h> #define inf 1e9 #define eps 1e-7 using namespace std; inline int read(){ int x=0;int f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } const int MAXN=100010; int a[4*MAXN],ans[4*MAXN]; int rsum; struct node{ int sum,L,R; }T[MAXN<<5]; int pos; int cut=0; int root[4*MAXN]={}; int n,m; namespace ZHANGENMING{ void inint(){ cin>>n>>m; for(int i=1;i<=n;i++){ a[i]=ans[i]=read(); } sort(a+1,a+n+1); rsum=unique(a+1,a+n+1)-(a+1); } int newnode(int id){ T[++cut].sum=T[id].sum+1; T[cut].L=T[id].L; T[cut].R=T[id].R; return cut; } int getnow(int s,int t,int rankk,int leftt,int rightt){ if(leftt==rightt) return leftt; int sum=T[T[t].L].sum-T[T[s].L].sum; int mid=(leftt+rightt)>>1; if(sum>=rankk) return getnow(T[s].L,T[t].L,rankk,leftt,mid); else return getnow(T[s].R,T[t].R,rankk-sum,mid+1,rightt); } void insert(int leftt,int rightt,int &root,int id){ root=newnode(id); if(leftt==rightt) return; int mid=(leftt+rightt)>>1; if(pos<=mid) insert(leftt,mid,T[root].L,T[id].L); else insert(mid+1,rightt,T[root].R,T[id].R); } void solve(){ for(int i=1;i<=n;i++){ pos=lower_bound(a+1,a+rsum+1,ans[i])-a; insert(1,rsum,root[i],root[i-1]); } for(int i=1;i<=m;i++){ int ll=read();int rr=read();int kk=read(); int t=getnow(root[ll-1],root[rr],kk,1,rsum); printf("%d ",a[t]); } } } int main(){ using namespace ZHANGENMING; inint(); solve(); return 0; }
主席树(带修改的区间第k大)
#include <bits/stdc++.h> #define ll long long using namespace std; inline int read(){ int x=0;int f=1;char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} return x*f; } const int MAXN=5e5+10; struct Chair_Man_Tree{ int son[2],sum; }T[MAXN]; struct node{ int a,b,k; char op; }Q[MAXN]; int arr[MAXN],fsort[MAXN],root[MAXN],rsum=0,sum=0,n,m,cnt=0,top[2],prevL[MAXN],prevR[MAXN]; namespace zhangenming{ inline int lowbit(int x) {return x&-x;} void init(){ n=read();m=read(); sum=n; for(int i=1;i<=n;i++){ fsort[i]=arr[i]=read(); } for(int i=1;i<=m;i++){ char op[5]; scanf("%s",op); Q[i].op=op[0];Q[i].a=read();Q[i].b=read(); if(op[0]=='Q') Q[i].k=read(); else fsort[++sum]=Q[i].b; } sort(fsort+1,fsort+sum+1); rsum=unique(fsort+1,fsort+sum+1)-fsort-1; } inline int Newnode(int sum,int son0,int son1){ T[++cnt].sum=sum;T[cnt].son[0]=son0; T[cnt].son[1]=son1;return cnt; } inline void build(int &root,int last,int pos,int leftt,int rightt){ root=Newnode(T[last].sum+1,T[last].son[0],T[last].son[1]); if(leftt==rightt) return; int mid=(rightt+leftt)>>1; if(pos<=mid) build(T[root].son[0],T[last].son[0],pos,leftt,mid); else build(T[root].son[1],T[last].son[1],pos,mid+1,rightt); } inline int Get(int leftt,int rightt,int rnk){ if(leftt==rightt) return leftt; int summ=0; for(int i=1;i<=top[0];i++) summ-=T[T[prevL[i]].son[0]].sum; for(int i=1;i<=top[1];i++) summ+=T[T[prevR[i]].son[0]].sum; int mid=(leftt+rightt)>>1; if(rnk<=summ){ for(int i=1;i<=top[0];i++) prevL[i]=T[prevL[i]].son[0]; for(int i=1;i<=top[1];i++) prevR[i]=T[prevR[i]].son[0]; return Get(leftt,mid,rnk); } else{ for(int i=1;i<=top[0];i++) prevL[i]=T[prevL[i]].son[1]; for(int i=1;i<=top[1];i++) prevR[i]=T[prevR[i]].son[1]; return Get(mid+1,rightt,rnk-summ); } } int k=0; inline void insert(int leftt,int rightt,int &root,int pos,int val){ if(!root) root=Newnode(0,0,0); T[root].sum+=val; if(leftt==rightt) return; int mid=(rightt+leftt)>>1; if(pos<=mid) insert(leftt,mid,T[root].son[0],pos,val); else insert(mid+1,rightt,T[root].son[1],pos,val); } void solve(){ for(int i=1;i<=n;i++){ arr[i]=lower_bound(fsort+1,fsort+rsum+1,arr[i])-fsort; build(root[i+n],root[i+n-1],arr[i],1,rsum); } for(int i=1;i<=m;i++){ if(Q[i].op=='Q'){ top[0]=top[1]=0; prevL[++top[0]]=root[((Q[i].a-1)==0?0:Q[i].a+n-1)]; prevR[++top[1]]=root[Q[i].b+n]; for(int j=Q[i].a-1;j>=1;j-=lowbit(j)){ prevL[++top[0]]=root[j]; } for(int j=Q[i].b;j>=1;j-=lowbit(j)){ prevR[++top[1]]=root[j]; } printf("%d ",fsort[Get(1,rsum,Q[i].k)]); } else{ for(int j=Q[i].a;j<=n;j+=lowbit(j)){ insert(1,rsum,root[j],arr[Q[i].a],-1); } arr[Q[i].a]=lower_bound(fsort+1,fsort+1+rsum,Q[i].b)-fsort; for(int j=Q[i].a;j<=n;j+=lowbit(j)){ insert(1,rsum,root[j],arr[Q[i].a],1); } } } } } int main(){ //freopen("All.in","r",stdin); //freopen("bai.out","w",stdout); using namespace zhangenming; init(); solve(); return 0; }