【模板】数据结构
一、栈/队列
栈模拟、括号匹配,单调栈
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
七、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; }