• 【模板】数据结构


    一、栈/队列

    栈模拟、括号匹配,单调栈

    noip:双栈排序

    二、并查集

    注意fa[]数组的初始值和路径压缩

    Noip:关押罪犯

    三、堆

     noip:合并果子

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define N 1000009
    using namespace std;
    
    int n,tot;
    
    int d[N];
    
    void up(int x){
        if(x==0)return;
        if(d[x]<d[x/2]){
            swap(d[x],d[x/2]);
            up(x/2);
        }
    }
    
    void down(int x){
        int nxt;
        if(x*2>tot)return;
        if(x*2+1>tot)nxt=x*2;
        else nxt=d[x*2]<d[x*2+1]?x*2:x*2+1;
        if(d[x]>d[nxt]){
            swap(d[x],d[nxt]);
            down(nxt);
        }
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            int od;
            scanf("%d",&od);
            if(od==1){
                int x;
                scanf("%d",&x);
                d[++tot]=x;
                up(tot);
            }
            if(od==2) printf("%d
    ",d[1]);
            if(od==3){
                d[1]=d[tot];
                tot--;
                down(1);
            }
        }
        return 0;
    }
    洛谷模板

    四、单调队列

    #include<iostream>
    #include<cstdio>
    using namespace std;
    int n,k,a[1000005],q[1000005],p[1000005];
    struct monotone_queue{
        int head,tail;
        void read(){
            scanf("%d%d",&n,&k);
            for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        }
        void monotone_max_(){
            head=1;tail=0;
            for(int i=1;i<=n;i++){
                while(head<=tail&&a[i]>q[tail])tail--;
                while(head<=tail&&p[head]<=i-k)head++;
                q[++tail]=a[i];p[tail]=i;
                if(i-k>=0)printf("%d ",q[head]);
            }
            printf("
    ");    
        }
        void monotone_min_(){
            head=1;tail=0;
            for(int i=1;i<=n;i++){
                while(head<=tail&&a[i]<q[tail])tail--;
                while(head<=tail&&p[head]<=i-k)head++;
                q[++tail]=a[i];p[tail]=i;
                if(i-k>=0)printf("%d ",q[head]);
            }
            printf("
    ");
        }
    }slove;
    int main(){
        slove.read();
        slove.monotone_min_();
        slove.monotone_max_();
        return 0;
    }
    滑动窗口

    五、线段树/树状数组

    CODEVS1080 线段树练习

    题目大意:单点修改区间查询

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define N 100009
    using namespace std;
    
    int n,m;
    
    int a[N];
    
    struct Tree{
        int l,r,sum;
    }tr[N<<2];
    
    void pushup(int rt){
        tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
        return;
    }
    
    void build(int rt,int l,int r){
        tr[rt].l=l;tr[rt].r=r;
        if(l==r){
            tr[rt].sum=a[l];
            return;
        }
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);
        build(rt<<1|1,mid+1,r);
        pushup(rt);
    }
    
    int query_sum(int rt,int l,int r,int ql,int qr){
        if(l>=ql&&r<=qr){
            return tr[rt].sum;
        }
        int ans=0,mid=(l+r)>>1;
        if(ql<=mid)ans+=query_sum(rt<<1,l,mid,ql,qr);
        if(qr>mid)ans+=query_sum(rt<<1|1,mid+1,r,ql,qr);
        return ans;
    }
    
    void change(int rt,int l,int r,int p,int c){
        if(l==r){
            tr[rt].sum+=c;
            return;
        }
        int mid=(l+r)>>1;
        if(p<=mid)change(rt<<1,l,mid,p,c);
        if(p>mid)change(rt<<1|1,mid+1,r,p,c);
        pushup(rt);
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        build(1,1,n);
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            int od,x,y;
            scanf("%d%d%d",&od,&x,&y);
            if(od==1)change(1,1,n,x,y);
            if(od==2)printf("%d
    ",query_sum(1,1,n,x,y));
        }
        return 0;
    }
    线段树
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define N 100009
    using namespace std;
    
    int n,m;
    
    int tree[N];
    
    int lowbit(int x){
        return x&(-x);
    }
    
    void add(int x,int p){
        while(x<=n){
            tree[x]+=p;
            x+=lowbit(x);
        }
    }
    
    int query(int x,int y){
        int sumx=0,sumy=0;
        x--;
        while(x){
            sumx+=tree[x];
            x-=lowbit(x);
        }
        while(y){
            sumy+=tree[y];
            y-=lowbit(y);
        }
        return sumy-sumx;
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);add(i,x);
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            int od,x,y;
            scanf("%d%d%d",&od,&x,&y);
            if(od==1)add(x,y);
            if(od==2)printf("%d
    ",query(x,y));
        }
        return 0;
    }
    树状数组

    CODEVS1081 线段树练习 2

    题目大意:区间修改单点查询

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define N 100009
    using namespace std;
    
    int n,m;
    
    int a[N];
    
    struct Tree{
        int l,r,sum,s;
    }tr[N<<2];
    
    void pushup(int rt){
        tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
    }
    
    void pushdown(int rt){
        if(tr[rt].s==0)return;
        tr[rt<<1].sum+=(tr[rt<<1].r-tr[rt<<1].l+1)*tr[rt].s;
        tr[rt<<1].s+=tr[rt].s;
        tr[rt<<1|1].sum+=(tr[rt<<1|1].r-tr[rt<<1|1].l+1)*tr[rt].s;
        tr[rt<<1|1].s+=tr[rt].s;
        tr[rt].s=0;
    }
    
    void build(int rt,int l,int r){
        tr[rt].l=l;tr[rt].r=r;
        if(l==r){
            tr[rt].sum=a[l];
            return;
        }
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
        pushup(rt);
    }
    
    void change(int rt,int l,int r,int ql,int qr,int c){
        if(l>=ql&&r<=qr){
            tr[rt].sum+=(r-l+1)*c;
            tr[rt].s+=c;
            return;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(ql<=mid)change(rt<<1,l,mid,ql,qr,c);
        if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr,c);
        pushup(rt);
    }
    
    int query(int rt,int l,int r,int p){
        if(l==r)return tr[rt].sum;
        pushdown(rt);
        int mid=(l+r)>>1;
        if(p<=mid)return query(rt<<1,l,mid,p);
        if(p>mid)return query(rt<<1|1,mid+1,r,p);
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        build(1,1,n);
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            int od;
            scanf("%d",&od);
            if(od==1){
                int l,r,x;
                scanf("%d%d%d",&l,&r,&x);
                change(1,1,n,l,r,x);
            }else{
                int p;
                scanf("%d",&p);
                printf("%d
    ",query(1,1,n,p));
            }
        }
        return 0;
    }
    线段树
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define N 100009
    using namespace std;
    
    int n,m,pre;
    
    int tree[N];
    
    int lowbit(int x){
        return x&(-x);
    }
    
    void add(int x,int y){
        while(x<=n+2){
            tree[x]+=y;
            x+=lowbit(x);
        }
    }
    
    int query(int x){
        int ans=0;
        while(x){
            ans+=tree[x];
            x-=lowbit(x);
        }
        return ans;
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            int x;
            scanf("%d",&x);
            add(i,x-pre);
            pre=x;
        }
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            int od;
            scanf("%d",&od);
            if(od==1){
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                add(x,z);add(y+1,-z);
            }else{
                int p;
                scanf("%d",&p);
                printf("%d
    ",query(p));
            }
        }
        return 0;
    }
    树状数组

    CODEVS1082 线段树练习 3

    题目大意:区间修改区间查询

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define N 200009
    #define LL long long
    using namespace std;
    
    int n,m;
    
    int a[N];
    
    struct Tree{
        int l,r;
        LL sum,s;
    }tr[N<<2];
    
    void pushup(int rt){
        tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum;
    }
    
    void pushdown(int rt){
        if(tr[rt].s==0)return;
        tr[rt<<1].sum+=(tr[rt<<1].r-tr[rt<<1].l+1)*tr[rt].s;
        tr[rt<<1].s+=tr[rt].s;
        tr[rt<<1|1].sum+=(tr[rt<<1|1].r-tr[rt<<1|1].l+1)*tr[rt].s;
        tr[rt<<1|1].s+=tr[rt].s;
        tr[rt].s=0;
    }
    
    void build(int rt,int l,int r){
        tr[rt].l=l;tr[rt].r=r;tr[rt].s=0;
        if(l==r){
            tr[rt].sum=a[l];
            return;
        }
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
        pushup(rt);
    }
    
    void change(int rt,int l,int r,int ql,int qr,int c){
        if(l>=ql&&r<=qr){
            tr[rt].sum+=(r-l+1)*c;
            tr[rt].s+=c;
            return;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(ql<=mid)change(rt<<1,l,mid,ql,qr,c);
        if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr,c);
        pushup(rt);
    }
    
    LL query_sum(int rt,int l,int r,int ql,int qr){
        if(l>=ql&&r<=qr){
            return tr[rt].sum;
        }
        pushdown(rt);
        int mid=(l+r)>>1;LL ans=0;
        if(ql<=mid)ans+=query_sum(rt<<1,l,mid,ql,qr);
        if(qr>mid)ans+=query_sum(rt<<1|1,mid+1,r,ql,qr);
        return ans;
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        build(1,1,n);
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            int od;
            scanf("%d",&od);
            if(od==1){
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                change(1,1,n,x,y,z);
            }else{
                int x,y;
                scanf("%d%d",&x,&y);
                printf("%lld
    ",query_sum(1,1,n,x,y));
            }
        }
        return 0;
    }
    线段树

    4919 线段树练习4

    题目大意:区间修改区间查询%7=0的数的个数

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define N 100009
    using namespace std;
    
    int n,m;
    
    int a[N],tmp[10];
    
    char s[10];
    
    struct Tree{
        int l,r,sum[7];
        int s;
    }tr[N<<2];
    
    void pushup(int rt){
        for(int i=0;i<7;i++)tr[rt].sum[i]=tr[rt<<1].sum[i]+tr[rt<<1|1].sum[i];
    }
    
    void pushdown(int rt){
        if(tr[rt].s==0)return;
        for(int i=0;i<7;i++)tmp[i]=tr[rt<<1].sum[i];
        for(int i=0;i<7;i++)tr[rt<<1].sum[(i+tr[rt].s)%7]=tmp[i];
        for(int i=0;i<7;i++)tmp[i]=tr[rt<<1|1].sum[i];
        for(int i=0;i<7;i++)tr[rt<<1|1].sum[(i+tr[rt].s)%7]=tmp[i];
        tr[rt<<1].s+=tr[rt].s;tr[rt<<1|1].s+=tr[rt].s;
        tr[rt].s=0;
    }
    
    void build(int rt,int l,int r){
        tr[rt].l=l;tr[rt].r=r;tr[rt].s=0;
        if(l==r){
            tr[rt].sum[a[l]%7]++;
            return;
        }
        int mid=(l+r)>>1;
        build(rt<<1,l,mid);build(rt<<1|1,mid+1,r);
        pushup(rt);
    }
    
    void change(int rt,int l,int r,int ql,int qr,int z){
        if(l>=ql&&r<=qr){
            for(int i=0;i<7;i++)tmp[i]=tr[rt].sum[i];
            for(int i=0;i<7;i++)tr[rt].sum[(i+z)%7]=tmp[i];
            tr[rt].s+=z;
            return;
        }
        pushdown(rt);
        int mid=(l+r)>>1;
        if(ql<=mid)change(rt<<1,l,mid,ql,qr,z);
        if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr,z);
        pushup(rt);
    }
    
    int query(int rt,int l,int r,int ql,int qr){
        if(l>=ql&&r<=qr) return tr[rt].sum[0];
        int mid=(l+r)>>1,ans=0;
        pushdown(rt);
        if(ql<=mid)ans+=query(rt<<1,l,mid,ql,qr);
        if(qr>mid)ans+=query(rt<<1|1,mid+1,r,ql,qr);
        return ans;
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        build(1,1,n);
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            scanf("%s",s);
            if(s[0]=='a'){
                int x,y,z;
                scanf("%d%d%d",&x,&y,&z);
                z%=7;
                change(1,1,n,x,y,z);
            }else{
                int l,r;
                scanf("%d%d",&l,&r);
                printf("%d
    ",query(1,1,n,l,r));
            }
        }
        return 0;
    }
    线段树

    六、链表

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 100009
    using namespace std;
    
    char s[maxn];
    int cur,last,next[maxn];
    
    int main(){
        while(scanf("%s",s+1)!=EOF){
            int len=strlen(s+1);
            next[0]=0;last=cur=0;
            for(int i=1;i<=len;i++){
                if(s[i]=='[')cur=0;
                else if(s[i]==']')cur=last;
                else{
                    next[i]=next[cur];
                    next[cur]=i;
                    if(cur==last)last=i;
                    cur=i;
                }
            }
            for(int i=next[0];i;i=next[i])
             printf("%c",s[i]);
            printf("
    ");
        }
        return 0;
    }
    
    AC
    codevs破损的键盘

    七、Trie树

    //p2580
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 500009
    using namespace std;
    
    int n,cnt,q,v[maxn],vis[maxn],trie[maxn][26];
    char s[maxn];
    
    void insert(){
        int root=0,len=strlen(s);
        for(int i=0;i<len;i++){
            int id=s[i]-'a';
            if(trie[root][id]==0)trie[root][id]=++cnt;
            root=trie[root][id];
        }
        v[root]=1;
    }
    
    int find(){
        int root=0,len=strlen(s);
        for(int i=0;i<len;i++){
            int id=s[i]-'a';
            if(trie[root][id]==0)return -1;
            root=trie[root][id];
        }
        if(!v[root])return -1;
        vis[root]++;
        return vis[root];
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%s",s);
            insert();
        }
        scanf("%d",&q);
        for(int i=1;i<=q;i++){
            scanf("%s",s);
            int p=find();
            if(p==-1)printf("WRONG
    ");
            else if(p==1)printf("OK
    ");
            else printf("REPEAT
    ");
        }
        return 0;
    }
    于是他错误的点名开始了
  • 相关阅读:
    jar
    8月21日23:38
    WPF之UI虚拟化
    (转)Windows系统白名单以及UAC机制
    C#获取文件版本信息
    命名实体识别,使用pyltp提取文本中的地址
    (转载)完成端口(Completion Port, I/OCP)详解
    全国各城市地名抓取,包含街道、村落、小区、商店、景点等
    关于Python打包运行的一些思路
    关于批判性思维(Critical Thinking)
  • 原文地址:https://www.cnblogs.com/zzyh/p/7795300.html
Copyright © 2020-2023  润新知