【模板】数据结构

一、栈/队列

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

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\n",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("\n");    
    }
    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("\n");
    }
}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\n",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\n",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\n",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\n",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\n",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\n",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("\n");
    }
    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\n");
        else if(p==1)printf("OK\n");
        else printf("REPEAT\n");
    }
    return 0;
}
于是他错误的点名开始了

 

posted @ 2017-11-06 21:31  ANhour  阅读(403)  评论(0编辑  收藏  举报