并查集
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<stdio.h> int stt[10005]; void sset(int x) { for(int i=1;i<=x;i++) stt[i]=i; } int ffind(int x) { if(x==stt[x]) return x; else return stt[x]=ffind(stt[x]); } void Union(int a,int b) { int x=ffind(a); int y=ffind(b); if(x==y) return; stt[y]=x; } int main() { sset(10000); /* */ }
树状数组 (一般单点修改 区间查询)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define int long long #define MAX(a,b,c) max(a,max(b,c)) #define MIN(a,b,c) min(a,min(b,c)) #define pb push_back #define fi first #define se second typedef long long ll; typedef long long LL; typedef unsigned long long ull; typedef unsigned long long uLL; using namespace std; const int maxn=5e5+10; const int INF=0x3f3f3f3f; int a[maxn]; int n; int lowbit(int x){return x&(-x); } void update(int b,int c) { while(b<=n) { a[b]+=c; b=b+lowbit(b); } } int getsum(int x) { int sum=0; while(x) { sum+=a[x]; x-=lowbit(x); } return sum; } int32_t main() { int q; cin>>n>>q; for(int i=1;i<=n;i++) { int x; cin>>x; update(i,x); } while(q--) { int x,b,c; cin>>x>>b>>c; if(x==1) {update(b,c);} if(x==2) { cout<<getsum(c)-getsum(b-1)<<endl; } } } 区间求值
一个其他学法的数组数组
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> //#define int long long #define MAX(a,b,c) max(a,max(b,c)) #define MIN(a,b,c) min(a,min(b,c)) #define pb push_back #define fi first #define se second typedef long long ll; typedef long long LL; typedef unsigned long long ull; typedef unsigned long long uLL; using namespace std; const int maxn=5e5+10; int a[maxn]; int n; int lowbit(int x){return x&(-x); } void update(int x,int c) { while(x) { a[x]+=c; x=x-lowbit(x); } } int getsum(int x) { int sum=0;; while(x<=n) { sum+=a[x]; x+=lowbit(x); }return sum; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int q; cin>>n>>q; for(int i=1;i<=n;i++) { int x; cin>>x; update(i,x); update(i-1,-x); } while(q--) { int x;cin>>x; if(x==1) { int a,b,c; cin>>a>>b>>c; update(b,c); update(a-1,-c);} if(x==2) { int a; cin>>a; cout<<getsum(a)<<endl;} } } 求点的值
线段树 模板
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define int long long using namespace std; const int maxn=1e5+10; struct NODE { int l,r,w,f; // f 为lazy标记 }tree[4*maxn+10]; void build(int p,int q,int k) { tree[k].l=p; tree[k].r=q; if(tree[k].l==tree[k].r) { cin>>tree[k].w;/* cout<<"==="<<tree[k].w<<endl;*/ return ; } int mid=( tree[k].l+tree[k].r )/2; build(p,mid,2*k); build(mid+1,q,2*k+1); tree[k].w=tree[2*k].w+tree[2*k+1].w; } void down(int k) // (lazy 标记) (××××) (important) { tree[2*k].f+=tree[k].f; tree[2*k+1].f+=tree[k].f; tree[k*2].w+=tree[k].f*(tree[k*2].r-tree[k*2].l+1); tree[k*2+1].w+=tree[k].f*(tree[k*2+1].r-tree[k*2+1].l+1); tree[k].f=0; } void change_interval(int a,int b,int x,int k) // 区间修改 区间加值; { if(tree[k].l>=a && tree[k].r<=b ) { tree[k].w+=(tree[k].r-tree[k].l+1)*x; tree[k].f+=x; return; } if(tree[k].f) down(k); int mid=(tree[k].l+tree[k].r)/2; if(b<=mid) change_interval(a,b,x,2*k); else if(a>=mid+1) change_interval(a,b,x,2*k+1); else change_interval(a,mid,x,2*k),change_interval(mid+1,b,x,2*k+1); tree[k].w=tree[k*2].w+tree[k*2+1].w; } void change_point(int x,int k) { if(tree[k].l==tree[k].r) { tree[k].w+=x; return; } if(tree[k].f) down(k); int mid=(tree[k].l+tree[k].r)/2; if(x<=mid) change_point(x,2*k); else change_point(x,2*k+1); tree[k].w=tree[k*2].w+tree[k*2+1].w; } int ask_interval(int a,int b,int k) // 区间查询 { int num=0; if(tree[k].l>=a&&tree[k].r<=b) { num+=tree[k].w; return num; } if(tree[k].f) down(k); int mid=( tree[k].l+tree[k].r)/2; if(b<=mid) num+=ask_interval(a,b,2*k); else if(a>=mid+1) num+=ask_interval(a,b,2*k+1); else num+=ask_interval(a,mid,2*k)+ask_interval(mid+1,b,2*k+1); return num; } int ask_point(int x,int k) // 点查询 { int num=0; if(tree[k].l==tree[k].r) {return tree[k].w; } if(tree[k].f) down(k); int mid=(tree[k].l+tree[k].r)/2; if(x<=mid) ask_point(x,2*k); if(x>=mid+1) ask_point(x,2*k+1); } int32_t main() { }
主席树 模板 hdu 2665
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> using namespace std; const int N=100005; const int M=100005*20; int root[N],lson[M],rson[M],v[M]; int a[N],b[N]; int tot=0; vector<int> vs; map<int,int> mp; void build(int &x,int l,int r){ x=++tot; //cout<<x<<endl; if(l==r) { v[x]=0; return; } int mid=(l+r)/2; build(lson[x],l,mid); build(rson[x],mid+1,r); v[x]=v[lson[x]]+v[rson[x]]; } void update(int odd,int &x,int pos,int value,int l,int r){ x=++tot; v[x]=v[odd]+value; lson[x]=lson[odd]; rson[x]=rson[odd]; // 构链 if(l==r) { return ; } int mid=(l+r)/2; if(mid>=pos) update(lson[odd],lson[x],pos,value,l,mid); else update(rson[odd],rson[x],pos,value,mid+1,r); //v[x]=v[lson[x]]+v[rson[x]]; } int query(int odd,int x,int k,int l,int r){ int num=v[lson[x]]-v[lson[odd]]; if(l==r) return l; if(k<=num) return query(lson[odd],lson[x],k,l,(l+r)/2); else return query(rson[odd],rson[x],k-num,(l+r)/2+1,r); } int main(){ int T; scanf("%d",&T); while(T--){ int n,m; scanf("%d %d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) vs.push_back(a[i]); sort(vs.begin(),vs.end()); vs.erase(unique(vs.begin(),vs.end()),vs.end()); for(int i=0;i<vs.size();i++) mp[vs[i]]=i+1,b[i+1]=vs[i]; //for(int i=0;i<vs.size();i++) cout<<vs[i]<<" "<<mp[vs[i]]<<endl; cout<<endl; int nn=vs.size(); build(root[0],1,nn); for(int i=1;i<=n;i++){ int pos=mp[a[i]]; //cout<<mp[a[i]]<<endl; update(root[i-1],root[i],pos,1,1,nn); } for(int i=1;i<=m;i++){ int l,r,k; scanf("%d %d %d",&l,&r,&k); int ans=query(root[l-1],root[r],k,1,nn); printf("%d\n",b[ans]); } vs.clear(); mp.clear(); for(int i=0;i<=n;i++) root[i]=0; tot=0; } }
dfs 线段树 poj3321
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<vector> using namespace std; const int maxn=1e5+10; pair<int,int> pa[maxn]; int head[maxn],cnt=0; struct EDGE { int next,to; } edge[maxn]; void ADD(int u,int v){ edge[++cnt].next=head[u]; edge[cnt].to=v; head[u]=cnt; } int tot=0; void dfs(int x,int fa){ pa[x].first=++tot; for(int i=head[x];i!=0;i=edge[i].next){ int u=edge[i].to; if(u==fa) continue; dfs(u,x); } pa[x].second=tot; } struct NODE { int l,r,w; }tree[4*maxn+10]; void build(int p,int q,int k){ tree[k].l=p; tree[k].r=q; if(tree[k].l==tree[k].r) { tree[k].w=1; return ; } int mid=( tree[k].l+tree[k].r )/2; build(p,mid,2*k); build(mid+1,q,2*k+1); tree[k].w=tree[2*k].w+tree[2*k+1].w; } void change_interval(int a,int b,int x,int k) // 区间修改 区间加值; { if(tree[k].l>=a && tree[k].r<=b ){ if(tree[k].w==1) tree[k].w=0; else tree[k].w=1; return; } int mid=(tree[k].l+tree[k].r)/2; if(b<=mid) change_interval(a,b,x,2*k); else if(a>=mid+1) change_interval(a,b,x,2*k+1); else change_interval(a,mid,x,2*k),change_interval(mid+1,b,x,2*k+1); tree[k].w=tree[k*2].w+tree[k*2+1].w; } int ask_interval(int a,int b,int k) // 区间查询 { int num=0; if(tree[k].l>=a&&tree[k].r<=b){ num=tree[k].w; return num; } int mid=( tree[k].l+tree[k].r)/2; if(b<=mid) num+=ask_interval(a,b,2*k); else if(a>=mid+1) num+=ask_interval(a,b,2*k+1); else num+=ask_interval(a,mid,2*k)+ask_interval(mid+1,b,2*k+1); return num; } char ch[2]; int c; int main(){ int n; scanf("%d",&n); for(int i=1;i<=n-1;i++){ int x,y; scanf("%d %d",&x,&y);ADD(x,y); } dfs(1,1); build(1,n,1); int q; scanf("%d",&q); while(q--){ scanf("%s %d",ch,&c); if(ch[0]=='Q') { printf("%d\n",ask_interval(pa[c].first,pa[c].second,1)); } else { change_interval(pa[c].first,pa[c].first,1,1); } } }
dfs序列 主席树 hdu 5678
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> #define ll long long using namespace std; const int maxn=4e5+10; const int mod=1e9+7; const int inv2=(1+mod)/2; int a[maxn],b[maxn]; pair<int,int> pa[maxn]; int head[maxn],cnt=0; struct EDGE { int next,to; } edge[maxn]; void ADD(int u,int v){ edge[++cnt].next=head[u]; edge[cnt].to=v; head[u]=cnt; } int tot=0; void dfs(int x,int fa){ pa[x].first=++tot; a[tot]=b[x]; for(int i=head[x];i!=0;i=edge[i].next){ int u=edge[i].to; if(u==fa) continue; dfs(u,x); } pa[x].second=tot; } int c[maxn*10]; int qqq[maxn*10]; int root[maxn],lson[maxn*20],rson[maxn*20],v[maxn*20]; void build(int &x,int l,int r){ x=++tot; //cout<<x<<endl; if(l==r) { v[x]=0; return; } int mid=(l+r)/2; build(lson[x],l,mid); build(rson[x],mid+1,r); v[x]=v[lson[x]]+v[rson[x]]; } void update(int odd,int &x,int pos,int value,int l,int r){ x=++tot; v[x]=v[odd]+value; lson[x]=lson[odd]; rson[x]=rson[odd]; // 构链 if(l==r) { return ; } int mid=(l+r)/2; if(mid>=pos) update(lson[odd],lson[x],pos,value,l,mid); else update(rson[odd],rson[x],pos,value,mid+1,r); } int query(int odd,int x,int k,int l,int r){ int num=v[lson[x]]-v[lson[odd]]; if(l==r) return l; if(k<=num) return query(lson[odd],lson[x],k,l,(l+r)/2); else return query(rson[odd],rson[x],k-num,(l+r)/2+1,r); } inline int read(){ int s=0,w=1; char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();} while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar(); return s*w; } map<int,int> mp; vector<int> vs; int kkk[maxn]; int main(){ c[0]=1; for(int i=1;i<maxn*10;i++){ c[i]=1ll*c[i-1]*10%mod; } int T; T=read(); while(T--){ vs.clear(); mp.clear(); cnt=0; tot=0; int n,q; n=read(); q=read(); for(int i=1;i<=n;i++) b[i]=read(); for(int i=1;i<=n;i++) vs.push_back(b[i]); sort(vs.begin(),vs.end()); vs.erase(unique(vs.begin(),vs.end()),vs.end()); for(int i=0;i<vs.size();i++) { mp[vs[i]]=i+1; kkk[i+1]=vs[i]; } for(int i=1;i<=n;i++) b[i]=mp[b[i]]; for(int i=1;i<=n-1;i++) { int x,y; x=read(); y=read(); ADD(x,y); } dfs(1,1); build(root[0],1,n); for(int i=1;i<=n;i++){ update(root[i-1],root[i],a[i],1,1,n); } ll ans=0; double f=0; for(int i=1;i<=q;i++){ int k; k=read(); int r=pa[k].second; int l=pa[k].first; int d=(r-l+1); if(d%2==1){ int w=(d+1)/2; int temp; if(qqq[k]==0 ) { temp=kkk[query(root[l-1],root[r],w,1,n)]; qqq[k]=temp; } temp=qqq[k]; ans+=1ll*temp*c[q-i]%mod; } else { int w=d/2; int temp=0; if(qqq[k]==0){ temp+=kkk[query(root[l-1],root[r],w,1,n)]+kkk[query(root[l-1],root[r],w+1,1,n)]; qqq[k]=temp; } temp=qqq[k]; if(i==q){ if(temp%2==1) f=0.5,ans+=temp/2; else ans+=1ll*temp/2%mod; } else { ans+=1ll*temp*5%mod*c[q-i-1]%mod; } } } f+=ans%mod; printf("%.1f\n",f); for(int i=1;i<=n;i++){ qqq[i]=0; head[i]=0; edge[i].next=0; edge[i].to=0; } } return 0; }
dfs序列 主席树 后缀自动机(主要用到后缀树 ) 树上倍增 / 后缀数组 主席树 st表 二分
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize(4) #include<bits/stdc++.h> #define ll long long using namespace std; const int mod=1e9+7; const int inv2=(1+mod)/2; int n,m; struct SAM { static const int MAXN = 200030<<1;//大小为字符串长度两倍 static const int maxn = 200030<<1; static const int LetterSize = 30; int tot, last, ch[MAXN][LetterSize], fa[MAXN], len[MAXN]; int num[maxn]; // 自动机->字符串结束位置 int renum[maxn]; // 结束位置-> 自动机位置 int num_0[maxn]; void init( void){ last = tot = 1; len[1] = 0; memset( ch[1], 0, sizeof ch[1]); } void add( int x,int c) { int p = last, np = last = ++tot; num[tot]=c+1; renum[c+1]=tot; // 记录结束位置 len[np] = len[p] + 1; memset( ch[np], 0, sizeof ch[np]); while( p && !ch[p][x]) ch[p][x] = np, p = fa[p]; if( p == 0) fa[np] = 1; else{ int q = ch[p][x]; if( len[q] == len[p] + 1) fa[np] = q; else { int nq = ++tot; memcpy( ch[nq], ch[q], sizeof ch[q]); len[nq] = len[p] + 1, fa[nq] = fa[q], fa[q] = fa[np] = nq; while( p && ch[p][x] == q) ch[p][x] = nq, p = fa[p]; } } } int root[maxn],lson[maxn*80],rson[maxn*80],v[maxn*80]; int w=0; void build(int &x,int l,int r){ x=++w; //cout<<x<<endl; if(l==r) { v[x]=0; return; } int mid=(l+r)/2; build(lson[x],l,mid); build(rson[x],mid+1,r); v[x]=v[lson[x]]+v[rson[x]]; } void update(int odd,int &x,int pos,int value,int l,int r){ x=++w; v[x]=v[odd]+value; lson[x]=lson[odd]; rson[x]=rson[odd]; // ¹¹Á´ if(l==r) { return ; } int mid=(l+r)/2; if(mid>=pos) update(lson[odd],lson[x],pos,value,l,mid); else update(rson[odd],rson[x],pos,value,mid+1,r); } int query(int odd,int x,int k,int l,int r){ int num=v[lson[x]]-v[lson[odd]]; if(l==r) return l; if(k<=num) return query(lson[odd],lson[x],k,l,(l+r)/2); else return query(rson[odd],rson[x],k-num,(l+r)/2+1,r); } vector<int> vs[maxn]; int bz[maxn][20]; int a[maxn]; //主席树上系列 -> 结束位置 pair<int,int> pa[maxn]; // dfs 序列 int k=0; void dfs(int x,int fa){ bz[x][0]=fa; pa[x].first=++k; a[k]=num[x]; // for(int i=1;i<=19;i++) bz[x][i]=bz[bz[x][i-1]][i-1]; // 树上倍增 for(int i=0;i<vs[x].size();i++){ dfs(vs[x][i],x);num_0[x]+=num_0[vs[x][i]]; } pa[x].second=k; if(num[x]==0) num_0[x]++; } void make_tu(){ for(int i=2;i<=tot;i++) vs[fa[i]].push_back(i);dfs(1,0); } void make(){ make_tu(); build(root[0],1,tot); for(int i=1;i<=tot;i++){ update(root[i-1],root[i],a[i]+1,1,1,tot+1); } } void slove(){ for(int i=1;i<=m;i++){ int l,r,k; scanf("%d %d %d",&l,&r,&k); int d=r-l+1; int pos=renum[r]; for(int i=19;i>=0;i--){ if(len[bz[pos][i]]>=d) pos=bz[pos][i]; } int lll=pa[pos].first; int rrr=pa[pos].second; int ddd=rrr-lll+1; if(k+num_0[pos]>ddd){ printf("-1\n"); } else { int w=query(root[lll-1],root[rrr],k+num_0[pos],1,tot+1); if(w==1) printf("-1\n"); else printf("%d\n",w-d); } } for(int i=0;i<=tot+10;i++){ vs[i].clear(); num_0[i]=0; num[i]=0; renum[i]=0; } k=0; } }sam; char ss[100005]; int main(){ int T; scanf("%d",&T); while(T--){ sam.init(); scanf("%d %d",&n,&m); scanf("%s",ss); for(int i=0;i<n;i++) sam.add(ss[i]-'a',i); sam.make(); sam.slove(); } return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #define rank rk using namespace std; const int maxn = 1050005; const int N=1050005; const int M=N*20; int sa[maxn], rank[maxn], height[maxn]; int wa[maxn], wb[maxn], wv[maxn], cnt[maxn]; void SA(int *r, int n, int m) { int *x = wa, *y = wb; for(int i = 0; i < m; i++) cnt[i] = 0; for(int i = 0; i < n; i++) cnt[x[i] = r[i]]++; for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1]; for(int i = n - 1; i >= 0; i--) sa[--cnt[x[i]]] = i; for(int j = 1; j < n; j <<= 1) { int p = 0; for(int i = n - j; i < n; i++) y[p++] = i; for(int i = 0; i < n; i++) if(sa[i] >= j) y[p++] = sa[i] - j; for(int i = 0; i < n; i++) wv[i] = x[y[i]]; for(int i = 0; i < m; i++) cnt[i] = 0; for(int i = 0; i < n; i++) cnt[wv[i]]++; for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1]; for(int i = n - 1; i >= 0; i--) sa[--cnt[wv[i]]] = y[i]; swap(x, y); p = 1; x[sa[0]] = 0; for(int i = 1; i < n; i++) x[sa[i]] = y[sa[i - 1]] == y[sa[i]] && y[sa[i - 1] + j] == y[sa[i] + j] ? p - 1 : p++; if(p >= n) break; m = p; } } void calcHeight(int *r, int n) { int i, j, k; for(i = j = k = 0; i < n; height[rank[i++]] = k) for(k ? k-- : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; k++); } int n, s[maxn]; int a[maxn]; char str[maxn]; int root[N],lson[M],rson[M],v[M]; int tot=0; void build(int &x,int l,int r){ x=++tot; //cout<<x<<endl; if(l==r) { v[x]=0; return; } int mid=(l+r)/2; build(lson[x],l,mid); build(rson[x],mid+1,r); v[x]=v[lson[x]]+v[rson[x]]; } void update(int odd,int &x,int pos,int value,int l,int r){ x=++tot; v[x]=v[odd]+value; lson[x]=lson[odd]; rson[x]=rson[odd]; // 构链 if(l==r) { return ; } int mid=(l+r)/2; if(mid>=pos) update(lson[odd],lson[x],pos,value,l,mid); else update(rson[odd],rson[x],pos,value,mid+1,r); } int query(int odd,int x,int k,int l,int r){ int num=v[lson[x]]-v[lson[odd]]; if(l==r) return l; if(k<=num) return query(lson[odd],lson[x],k,l,(l+r)/2); else return query(rson[odd],rson[x],k-num,(l+r)/2+1,r); } int lg[maxn]; int st[maxn][20]; void make_ST(){ for(int i=n;i>=1;i--){ st[i][0]=height[i]; for(int j=1;i+(1<<j-1)-1<=n;j++){ st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]); } // cout<<st[i][0]<<endl; } } bool st_check(int l,int r,int d){ if(l==r) return 1; l++; int k=lg[r-l+1]; int m=min(st[l][k],st[r-(1<<k)+1][k]); if(m>=d) return 1; else return 0; } int check1(int l,int r,int d){ int x=l; int mid=(l+r)/2; while(l<r){ if(st_check(x,mid,d)) l=mid; else r=mid-1; mid=(l+r+1)/2; } return mid; } int check2(int l,int r,int d){ int x=r; int mid=(l+r)/2; while(l<r){ // cout<<l<<" "<<r<<" "<<mid<<" "<<st_check(mid,x,d)<<endl;; if(st_check(mid,x,d)) r=mid; else l=mid+1; mid=(l+r)/2; } return mid; } void make(int l,int r,int k){ int d=(r-l+1); int pos=rank[l-1]; int rr,ll; rr=check1(pos,n,d); ll=check2(1,pos,d); int w=rr-ll+1; if(w<k) printf("-1\n"); else { int ans=query(root[ll-1],root[rr],k,1,n); printf("%d\n",ans); } } int main() { for(int i=2;i<maxn;i++){lg[i]=lg[i>>1]+1;} int T; scanf("%d", &T); while(T--) { int q; scanf("%d %d",&n,&q); scanf("%s", str); n = strlen(str); for(int i = 0; i < n; i++) s[i] = str[i]; s[n] = 0; SA(s, n + 1, 300); for(int i = 0; i <= n; i++) rank[sa[i]] = i; calcHeight(s, n); make_ST(); int nn=n; build(root[0],1,nn); for(int i=1;i<=n;i++) a[i]=sa[i]+1; // for(int i=1;i<=n;i++) cout<<a[i]<<" "; cout<<endl; for(int i=1;i<=n;i++) update(root[i-1],root[i],a[i],1,1,nn); while(q--){ int l,r,k; scanf("%d %d %d",&l,&r,&k); make(l,r,k); } } return 0; }