zoukankan      html  css  js  c++  java
  • 数据结构

     

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

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

    虽然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;
    }
  • 相关阅读:
    【2020-04-14】吃一折,长一智吧
    对“沟通成本”模型的一个重新假设
    【2020-04-13】稀缺才能让人珍惜
    【2020-04-12】决策都是当前认知的反映
    hhhhh我进步啦!
    求后序遍历(信息学奥赛一本通 1339)
    数的划分(信息学奥赛一本通 1304 洛谷 1025)
    memset函数怎么用嘞↓↓↓
    stack函数怎么用嘞?↓↓↓
    终于开通博客啦!
  • 原文地址:https://www.cnblogs.com/something-for-nothing/p/7798293.html
Copyright © 2011-2022 走看看