数据结构

 

数据结构这种东西敲起来十分爽

数据结构往往替代了我们思考的过程,但还是比较好用的

虽然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\n",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\n",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\n",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;
}

 

posted @ 2017-11-07 11:42  zhangenming  阅读(297)  评论(0编辑  收藏  举报