线段树
//BZOJ 1455
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_n=1e6+5;
const int max_m=1e5+5;
int n,m,x,y,fx,fy,top;
int f[max_n],lst[max_n],rst[max_n],disst[max_n],keyst[max_n]; char opt;
bool have_killed[max_n];
inline int find(int x){if (x==f[x]) return x;else return f[x]=find(f[x]);}
inline int merge(int x,int y){
if (!x) return y;
if (!y) return x;
if (keyst[x]>keyst[y]) swap(x,y);
rst[x]=merge(rst[x],y);
if (disst[rst[x]]>disst[lst[x]]) swap(rst[x],lst[x]);
disst[x]=disst[rst[x]]+1;
return x;
}
inline void pop(int x){
f[x]=merge(lst[x],rst[x]);
f[f[x]]=f[x];
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;++i) scanf("%d",&keyst[i]),f[i]=i;
scanf("%d",&m);
for (int i=1;i<=m;++i){
opt=getchar();
while (opt!='M'&&opt!='K') opt=getchar();
if (opt=='M')
{
scanf("%d%d",&x,&y);
if (have_killed[x]||have_killed[y]) continue;
fx=find(x),fy=find(y);
if (fx!=fy)
top=merge(fx,fy),f[fx]=f[fy]=top;
}
else
{
scanf("%d",&x);
if (have_killed[x]) {printf("0\n");continue;}
fx=find(x); have_killed[fx]=true; printf("%d\n",keyst[fx]);
pop(fx);
}
}
}
// codevs 1081
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_n=1e5+5;
int a[max_n],sum[max_n*2],delta[max_n*2];
int n,m,order,x,v,lrange,rrange,ans;
inline void update(int now){
sum[now]=sum[now<<1]+sum[now<<1|1];
}
inline void pushdown(int now,int l,int r,int mid){
if (delta[now]){
sum[now<<1]+=delta[now]*(mid-l+1);
delta[now<<1]+=delta[now];
sum[now<<1|1]+=delta[now]*(r-mid);
delta[now<<1|1]+=delta[now];
delta[now]=0;
}
}
inline void build(int now,int l,int r){
int mid=(l+r)>>1;
if (l==r){
sum[now]=a[l];
return;
}
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
update(now);
}
inline void interval_change(int now,int l,int r,int lrange,int rrange,int v){
int mid=(l+r)>>1;
if (lrange<=l&&r<=rrange){
sum[now]+=v*(r-l+1);
delta[now]+=v;
return;
}
pushdown(now,l,r,mid);
if (lrange<=mid)
interval_change(now<<1,l,mid,lrange,rrange,v);
if (mid+1<=rrange)
interval_change(now<<1|1,mid+1,r,lrange,rrange,v);
update(now);
}
inline int query(int now,int l,int r,int lrange,int rrange){
int mid=(l+r)>>1,ans=0;
if (lrange<=l&&r<=rrange) return sum[now];
pushdown(now,l,r,mid);
if (lrange<=mid)
ans+=query(now<<1,l,mid,lrange,rrange);
if (mid+1<=rrange)
ans+=query(now<<1|1,mid+1,r,lrange,rrange);
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("%d",&order);
if (order==1){
scanf("%d%d%d",&lrange,&rrange,&v);
interval_change(1,1,n,lrange,rrange,v);
}
else{
scanf("%d",&x);
ans=query(1,1,n,x,x);
printf("%d\n",ans);
}
}
}
平衡树
// BZOJ 3224
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define MAXN 1000000
int ch[MAXN][2],f[MAXN],size[MAXN],cnt[MAXN],key[MAXN];
int sz,root;
inline void clear(int x){
ch[x][0]=ch[x][1]=f[x]=size[x]=cnt[x]=key[x]=0;
}
inline bool get(int x){
return ch[f[x]][1]==x;
}
inline void update(int x){
if (x){
size[x]=cnt[x];
if (ch[x][0]) size[x]+=size[ch[x][0]];
if (ch[x][1]) size[x]+=size[ch[x][1]];
}
}
inline void rotate(int x){
int old=f[x],oldf=f[old],whichx=get(x);
ch[old][whichx]=ch[x][whichx^1]; f[ch[old][whichx]]=old;
ch[x][whichx^1]=old; f[old]=x;
f[x]=oldf;
if (oldf)
ch[oldf][ch[oldf][1]==old]=x;
update(old); update(x);
}
inline void splay(int x){
for (int fa;fa=f[x];rotate(x))
if (f[fa])
rotate((get(x)==get(fa))?fa:x);
root=x;
}
inline void insert(int x){
if (root==0){sz++; ch[sz][0]=ch[sz][1]=f[sz]=0; root=sz; size[sz]=cnt[sz]=1; key[sz]=x; return;}
int now=root,fa=0;
while(1){
if (x==key[now]){
cnt[now]++; update(now); update(fa); splay(now); break;
}
fa=now;
now=ch[now][key[now]<x];
if (now==0){
sz++;
ch[sz][0]=ch[sz][1]=0;
f[sz]=fa;
size[sz]=cnt[sz]=1;
ch[fa][key[fa]<x]=sz;
key[sz]=x;
update(fa);
splay(sz);
break;
}
}
}
inline int find(int x){
int now=root,ans=0;
while(1){
if (x<key[now])
now=ch[now][0];
else{
ans+=(ch[now][0]?size[ch[now][0]]:0);
if (x==key[now]){
splay(now); return ans+1;
}
ans+=cnt[now];
now=ch[now][1];
}
}
}
inline int findx(int x){
int now=root;
while(1){
if (ch[now][0]&&x<=size[ch[now][0]])
now=ch[now][0];
else{
int temp=(ch[now][0]?size[ch[now][0]]:0)+cnt[now];
if (x<=temp) return key[now];
x-=temp; now=ch[now][1];
}
}
}
inline int pre(){
int now=ch[root][0];
while (ch[now][1]) now=ch[now][1];
return now;
}
inline int next(){
int now=ch[root][1];
while (ch[now][0]) now=ch[now][0];
return now;
}
inline void del(int x){
int whatever=find(x);
if (cnt[root]>1){cnt[root]--; update(root); return;}
if (!ch[root][0]&&!ch[root][1]) {clear(root); root=0; return;}
if (!ch[root][0]){
int oldroot=root; root=ch[root][1]; f[root]=0; clear(oldroot); return;
}
else if (!ch[root][1]){
int oldroot=root; root=ch[root][0]; f[root]=0; clear(oldroot); return;
}
int leftbig=pre(),oldroot=root;
splay(leftbig);
ch[root][1]=ch[oldroot][1];
f[ch[oldroot][1]]=root;
clear(oldroot);
update(root);
}
int main(){
int n,opt,x;
scanf("%d",&n);
for (int i=1;i<=n;++i){
scanf("%d%d",&opt,&x);
switch(opt){
case 1: insert(x); break;
case 2: del(x); break;
case 3: printf("%d\n",find(x)); break;
case 4: printf("%d\n",findx(x)); break;
case 5: insert(x); printf("%d\n",key[pre()]); del(x); break;
case 6: insert(x); printf("%d\n",key[next()]); del(x); break;
}
}
}
// BZOJ 3223
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define MAXN 110000
#define INF 1000000000
int ch[MAXN][2],f[MAXN],size[MAXN],key[MAXN],delta[MAXN],a[MAXN];
int n,m,x,y,sz,root;
inline void update(int x){
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
inline bool get(int x){
return ch[f[x]][1]==x;
}
inline void pushdown(int x){
if (x&&delta[x]){
delta[ch[x][0]]^=1;
delta[ch[x][1]]^=1;
swap(ch[x][0],ch[x][1]);
delta[x]=0;
}
}
inline int build(int left,int right,int fa){
if (left>right) return 0;
int mid=(left+right)>>1;
int now=++sz;
key[now]=a[mid]; f[now]=fa; delta[now]=0;
int leftchild=build(left,mid-1,now);
int rightchild=build(mid+1,right,now);
ch[now][0]=leftchild; ch[now][1]=rightchild; update(now);
return now;
}
inline void rotate(int x){
pushdown(f[x]); pushdown(x);
int old=f[x],oldf=f[old],which=get(x);
ch[old][which]=ch[x][which^1]; f[ch[old][which]]=old;
ch[x][which^1]=old; f[old]=x;
f[x]=oldf;
if (oldf)
ch[oldf][ch[oldf][1]==old]=x;
update(old); update(x);
}
inline void splay(int x,int tar){
for (int fa;(fa=f[x])!=tar;rotate(x))
if (f[fa]!=tar)
rotate((get(x)==get(fa))?fa:x);
if (tar==0) root=x;
}
inline int find(int x){
int now=root;
while(1){
pushdown(now);
if (x<=size[ch[now][0]])
now=ch[now][0];
else{
x-=size[ch[now][0]]+1;
if (x==0) return now;
now=ch[now][1];
}
}
}
inline void print(int now){
pushdown(now);
if (ch[now][0]) print(ch[now][0]);
if (key[now]!=INF&&key[now]!=-INF) printf("%d ",key[now]);
if (ch[now][1]) print(ch[now][1]);
}
int main(){
scanf("%d%d",&n,&m);
a[1]=-INF; a[n+2]=INF;
for (int i=1;i<=n;++i)
a[i+1]=i;
root=build(1,n+2,0);
for (int i=1;i<=m;++i){
scanf("%d%d",&x,&y);
if (x>=y) continue;
int aa=find(x);
int bb=find(y+2);
splay(aa,0);
splay(bb,aa);
delta[ch[ch[root][1]][0]]^=1;
}
print(root);
printf("\n");
}
树链剖分
// BZOJ 1036
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_n=3e4+5;
const int max_e=max_n*4;
const int max_N=max_n*4+5;
const int mininf=-2100000000;
int n,x,y,N,q,u,t,ans,f1,f2;
int w[max_n],size[max_n],h[max_n],father[max_n],son[max_n];
int top[max_n],num[max_n],tree[max_n];
int point[max_n],next[max_e],v[max_e],tot;
char order[10];
int sum[max_N],maxn[max_N];
inline void add(int x,int y){
++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y;
++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x;
}
inline void dfs_1(int x,int fa,int dep){
size[x]=1; h[x]=dep; father[x]=fa;
int maxson=0;
for (int i=point[x];i;i=next[i])
if (v[i]!=fa){
dfs_1(v[i],x,dep+1);
size[x]+=size[v[i]];
if (size[v[i]]>maxson){
maxson=size[v[i]];
son[x]=v[i];
}
}
}
inline void dfs_2(int x,int fa){
if (son[fa]!=x) top[x]=x;
else top[x]=top[fa];
num[x]=++N;
if (son[x]) dfs_2(son[x],x);
for (int i=point[x];i;i=next[i])
if (v[i]!=fa&&v[i]!=son[x])
dfs_2(v[i],x);
}
inline void update_sum(int now){
sum[now]=sum[now<<1]+sum[now<<1|1];
}
inline void update_max(int now){
maxn[now]=max(maxn[now<<1],maxn[now<<1|1]);
}
inline void build_sum(int now,int l,int r){
int mid=(l+r)>>1;
if (l==r){
sum[now]=w[tree[l]];
return;
}
build_sum(now<<1,l,mid);
build_sum(now<<1|1,mid+1,r);
update_sum(now);
}
inline void build_max(int now,int l,int r){
int mid=(l+r)>>1;
if (l==r){
maxn[now]=w[tree[l]];
return;
}
build_max(now<<1,l,mid);
build_max(now<<1|1,mid+1,r);
update_max(now);
}
inline void point_change_sum(int now,int l,int r,int x,int v){
int mid=(l+r)>>1;
if (l==r){
sum[now]=v;
return;
}
if (x<=mid)
point_change_sum(now<<1,l,mid,x,v);
else
point_change_sum(now<<1|1,mid+1,r,x,v);
update_sum(now);
}
inline void point_change_max(int now,int l,int r,int x,int v){
int mid=(l+r)>>1;
if (l==r){
maxn[now]=v;
return;
}
if (x<=mid)
point_change_max(now<<1,l,mid,x,v);
else
point_change_max(now<<1|1,mid+1,r,x,v);
update_max(now);
}
inline int query_sum(int now,int l,int r,int lrange,int rrange){
int mid=(l+r)>>1,ans=0;
if (lrange<=l&&r<=rrange) return sum[now];
if (lrange<=mid)
ans+=query_sum(now<<1,l,mid,lrange,rrange);
if (mid+1<=rrange)
ans+=query_sum(now<<1|1,mid+1,r,lrange,rrange);
return ans;
}
inline int query_max(int now,int l,int r,int lrange,int rrange){
int mid=(l+r)>>1,ans=mininf;
if (lrange<=l&&r<=rrange) return maxn[now];
if (lrange<=mid)
ans=max(ans,query_max(now<<1,l,mid,lrange,rrange));
if (mid+1<=rrange)
ans=max(ans,query_max(now<<1|1,mid+1,r,lrange,rrange));
return ans;
}
int main(){
scanf("%d",&n);
for (int i=1;i<n;++i){
scanf("%d%d",&x,&y);
add(x,y);
}
for (int i=1;i<=n;++i) scanf("%d",&w[i]);
dfs_1(1,0,1);
dfs_2(1,0);
for (int i=1;i<=n;++i)
tree[num[i]]=i;
build_sum(1,1,N);
build_max(1,1,N);
scanf("%d",&q);
for (int i=1;i<=q;++i){
scanf("%s",order);
while (strlen(order)<4) scanf("%s",order);
scanf("%d%d",&u,&t);
if (order[0]=='C'){
point_change_sum(1,1,N,num[u],t);
point_change_max(1,1,N,num[u],t);
}
else{
if (order[1]=='S'){
ans=0;
f1=top[u],f2=top[t];
while (f1!=f2){
if (h[f1]<h[f2]){
swap(u,t);
swap(f1,f2);
}
ans+=query_sum(1,1,N,num[f1],num[u]);
u=father[f1];
f1=top[u];
}
if (num[u]>num[t]) swap(u,t);
ans+=query_sum(1,1,N,num[u],num[t]);
printf("%d\n",ans);
}
else{
ans=mininf;
f1=top[u],f2=top[t];
while (f1!=f2){
if (h[f1]<h[f2]){
swap(u,t);
swap(f1,f2);
}
ans=max(ans,query_max(1,1,N,num[f1],num[u]));
u=father[f1];
f1=top[u];
}
if (num[u]>num[t]) swap(u,t);
ans=max(ans,query_max(1,1,N,num[u],num[t]));
printf("%d\n",ans);
}
}
}
}
dfs序
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_n=1e5+5;
const int max_e=max_n;
const int max_tree=max_n*4;
const int INF=2147483647;
int n,m,N,fa,root,x,y;
int tot,point[max_n],next[max_e],v[max_e];
int a[max_n],father[max_n],in[max_n],out[max_n],val[max_n];
int tree[max_tree];
inline void addedge(int x,int y){++tot;next[tot]=point[x];point[x]=tot;v[tot]=y;}
inline void dfs(int x,int fa){
father[x]=fa; in[x]=++N; val[N]=a[x];
for (int i=point[x];i;i=next[i])
if (v[i]!=fa)
dfs(v[i],x);
out[x]=N;
}
inline void update(int now){
tree[now]=min(tree[now<<1],tree[now<<1|1]);
}
inline void build(int now,int l,int r){
int mid=(l+r)>>1;
if (l==r){
tree[now]=val[l];
return;
}
build(now<<1,l,mid);
build(now<<1|1,mid+1,r);
update(now);
}
inline void point_change(int now,int l,int r,int x,int v){
int mid=(l+r)>>1;
if (l==r){
tree[now]=v;
return;
}
if (x<=mid) point_change(now<<1,l,mid,x,v);
else point_change(now<<1|1,mid+1,r,x,v);
update(now);
}
inline int query(int now,int l,int r,int lrange,int rrange){
int mid=(l+r)>>1,ans=INF;
if (lrange<=l&&r<=rrange) return tree[now];
if (lrange<=mid) ans=min(ans,query(now<<1,l,mid,lrange,rrange));
if (mid+1<=rrange) ans=min(ans,query(now<<1|1,mid+1,r,lrange,rrange));
return ans;
}
inline int ask(int x){
if (root==x) return query(1,1,N,1,N);
if (!(in[root]>=in[x]&&in[root]<=out[x])) return query(1,1,N,in[x],out[x]);
int ans=INF;
for (int i=point[x];i;i=next[i])
if (v[i]!=father[x]&&in[root]>=in[v[i]]&&in[root]<=out[v[i]]){
if (1<=in[v[i]]-1) ans=min(ans,query(1,1,N,1,in[v[i]]-1));
if (out[v[i]]+1<=N) ans=min(ans,query(1,1,N,out[v[i]]+1,N));
break;
}
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i){
scanf("%d%d",&fa,&a[i]);
if (fa) addedge(fa,i);
else root=i;
}
dfs(root,0);
build(1,1,N);
for (int i=1;i<=m;++i){
char opt=getchar();
while (opt!='V'&&opt!='E'&&opt!='Q') opt=getchar();
if (opt=='V'){
scanf("%d%d",&x,&y);
point_change(1,1,N,in[x],y);
}
if (opt=='E'){
scanf("%d",&x);
root=x;
}
if (opt=='Q'){
scanf("%d",&x);
int ans=ask(x);
printf("%d\n",ans);
}
}
}
LCT
// CODEVS 1839
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_n=1e4+5;
int n,m,x,y;
char opt[10];
int f[max_n],ch[max_n][2],strack[max_n],delta[max_n];
inline int get(int x)
{
return ch[f[x]][1]==x;
}
inline bool is_root(int x)
{
return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;
}
inline void pushdown(int x)
{
if (x&&delta[x])
{
swap(ch[x][0],ch[x][1]);
if (ch[x][0]) delta[ch[x][0]]^=1;
if (ch[x][1]) delta[ch[x][1]]^=1;
delta[x]=0;
}
}
inline void rotate(int x)
{
int old=f[x],oldf=f[old],which=get(x);
if (!is_root(old))
ch[oldf][ch[oldf][1]==old]=x;
f[x]=oldf;
ch[old][which]=ch[x][which^1];
f[ch[old][which]]=old;
ch[x][which^1]=old;
f[old]=x;
}
inline void splay(int x)
{
int top=0;
strack[++top]=x;
for (int i=x;!is_root(i);i=f[i])
strack[++top]=f[i];
for (int i=top;i>=1;--i)
pushdown(strack[i]);
for (int fa;!is_root(x);rotate(x))
if (!is_root(fa=f[x]))
rotate((get(x)==get(fa))?fa:x);
}
inline void access(int x)
{
int t=0;
for (;x;t=x,x=f[x])
{
splay(x);
ch[x][1]=t;
}
}
inline void reverse(int x)
{
access(x);
splay(x);
delta[x]^=1;
}
inline void link(int x,int y)
{
reverse(x);
f[x]=y;
splay(x);
}
inline void cut(int x,int y)
{
reverse(x);
access(y);
splay(y);
ch[y][0]=f[x]=0;
}
inline int find(int x)
{
access(x);
splay(x);
while (ch[x][0]) x=ch[x][0];
return x;
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;++i)
{
scanf("%s",opt);
if (opt[0]=='Q')
{
scanf("%d%d",&x,&y);
if (find(x)!=find(y)) printf("No\n");
else printf("Yes\n");
}
if (opt[0]=='C')
{
scanf("%d%d",&x,&y);
link(x,y);
}
if (opt[0]=='D')
{
scanf("%d%d",&x,&y);
cut(x,y);
}
}
}
主席树
// POJ 2104
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_n=1e5+5;
int n,m,x,y,z,sz,ans;
int val[max_n],p[max_n],num[max_n],root[max_n];
int sum[max_n*20],ls[max_n*20],rs[max_n*20];
inline int cmp(int a,int b){return val[a]<val[b];}
inline void build(int &now,int l,int r,int x){
int mid=(l+r)>>1;
sum[++sz]=sum[now]; ls[sz]=ls[now]; rs[sz]=rs[now];
now=sz;
++sum[now];
if (l==r) return;
if (x<=mid) build(ls[now],l,mid,x);
else build(rs[now],mid+1,r,x);
}
inline int query(int i,int j,int l,int r,int k){
int mid=(l+r)>>1;
if (l==r) return l;
int t=sum[ls[j]]-sum[ls[i]];
if (t>=k) return query(ls[i],ls[j],l,mid,k);
else return query(rs[i],rs[j],mid+1,r,k-t);
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i) scanf("%d",&val[i]),p[i]=i;
sort(p+1,p+n+1,cmp);
for (int i=1;i<=n;++i)
num[p[i]]=i;
sz=0; root[0]=0;
for (int i=1;i<=n;++i){
root[i]=root[i-1];
build(root[i],1,n,num[i]);
}
for (int i=1;i<=m;++i){
scanf("%d%d%d",&x,&y,&z);
ans=query(root[x-1],root[y],1,n,z);
printf("%d\n",val[p[ans]]);
}
}
// BZOJ 1901
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_n=1e4+5;
const int max_m=1e4+5;
const int max_log=30;
const int max_tree=3e6+5;
char opt[10];
int n,m,a,b,t,sz,N,cnt;
int val[max_n],A[max_m],B[max_m],K[max_m],flag[max_m];
int num[max_n*2],hash[max_n*2],root[max_n*2],L[max_log],R[max_log];
int sum[max_tree],ls[max_tree],rs[max_tree];
inline int find(int x){
int l=1,r=N,mid;
while (l<=r){
mid=(l+r)>>1;
if (hash[mid]<x) l=mid+1;
else r=mid-1;
}
return l;
}
inline void build(int last,int l,int r,int &now,int x,int v){
int mid=(l+r)>>1;
now=++sz;
sum[now]=sum[last]+v; ls[now]=ls[last]; rs[now]=rs[last];
if (l==r) return;
if (x<=mid) build(ls[last],l,mid,ls[now],x,v);
else build(rs[last],mid+1,r,rs[now],x,v);
}
inline int query(int l,int r,int k){
int mid=(l+r)>>1;
if (l==r) return l;
int suml=0,sumr=0;
for (int i=1;i<=a;++i) suml+=sum[ls[L[i]]];
for (int i=1;i<=b;++i) sumr+=sum[ls[R[i]]];
if (sumr-suml>=k){
for (int i=1;i<=a;++i) L[i]=ls[L[i]];
for (int i=1;i<=b;++i) R[i]=ls[R[i]];
return query(l,mid,k);
}
else{
for (int i=1;i<=a;++i) L[i]=rs[L[i]];
for (int i=1;i<=b;++i) R[i]=rs[R[i]];
return query(mid+1,r,k-(sumr-suml));
}
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i) scanf("%d",&val[i]),num[++cnt]=val[i];
for (int i=1;i<=m;++i){
scanf("%s",opt);
if (opt[0]=='C'){
scanf("%d%d",&A[i],&B[i]);
num[++cnt]=B[i];
}
else{
flag[i]=1;
scanf("%d%d%d",&A[i],&B[i],&K[i]);
}
}
sort(num+1,num+cnt+1);
hash[++N]=num[1];
for (int i=2;i<=cnt;++i)
if (num[i]!=num[i-1]) hash[++N]=num[i];
for (int i=1;i<=n;++i){
t=find(val[i]);
for (int j=i;j<=n;j+=j&(-j))
build(root[j],1,N,root[j],t,1);
}
for (int i=1;i<=m;++i)
if (flag[i]){
a=0,b=0,A[i]--;
for (int j=A[i];j>=1;j-=j&(-j)) L[++a]=root[j];
for (int j=B[i];j>=1;j-=j&(-j)) R[++b]=root[j];
printf("%d\n",hash[query(1,N,K[i])]);
}
else{
t=find(val[A[i]]);
for (int j=A[i];j<=n;j+=j&(-j)) build(root[j],1,N,root[j],t,-1);
val[A[i]]=B[i];
t=find(val[A[i]]);
for (int j=A[i];j<=n;j+=j&(-j)) build(root[j],1,N,root[j],t,1);
}
}
网络流
EK
// codevs 1993
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int inf=2100000000;
int n,m,maxflow,a[205][205],flow[205],pre[205];
int x,y,cap;
queue <int> q;
inline int bfs(int s,int t){
while (!q.empty()) q.pop();
for (int i=1;i<=m;++i) pre[i]=-1;
pre[s]=0;
q.push(s);
flow[s]=inf;
while (!q.empty()){
int x=q.front();
q.pop();
if (x==t) break;
for (int i=1;i<=m;++i)
//EK一次只找一个增广路
if (a[x][i]>0&&pre[i]==-1){
pre[i]=x;
flow[i]=min(flow[x],a[x][i]);
q.push(i);
}
}
if (pre[t]==-1) return -1;
else return flow[t];
}
inline void ek(int s,int t){
int increase=0;
while ((increase=bfs(s,t))!=-1){
int k=t;
while (k!=s){
int last=pre[k];
a[last][k]-=increase;
a[k][last]+=increase;
k=last;
}
maxflow+=increase;
}
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i){
scanf("%d%d%d",&x,&y,&cap);
a[x][y]+=cap;
}
ek(1,m);
printf("%d\n",maxflow);
}
dinic
// codevs 1993
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int max_n=205;
const int max_m=205;
const int max_e=max_m*2;
const int inf=1e9;
int point[max_n],next[max_e],v[max_e],remain[max_e],deep[max_n],cur[max_n];
int n,m,x,y,cap,tot,maxflow;
queue <int> q;
inline void add(int x,int y,int cap){
++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=cap;
++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0;
}
inline bool bfs(int s,int t){
memset(deep,0x7f,sizeof(deep));
deep[s]=0;
for (int i=1;i<=n;++i)
cur[i]=point[i];
while (!q.empty()) q.pop();
q.push(s);
while (!q.empty()){
int now=q.front(); q.pop();
for (int i=point[now];i!=-1;i=next[i])
if (deep[v[i]]>inf&&remain[i]){
deep[v[i]]=deep[now]+1;
q.push(v[i]);
}
}
return deep[t]<inf;
}
inline int dfs(int now,int t,int limit){
if (!limit||now==t) return limit;
int flow=0,f;
for (int i=cur[now];i!=-1;i=next[i]){
cur[now]=i;
if (deep[v[i]]==deep[now]+1&&(f=dfs(v[i],t,min(limit,remain[i])))){
flow+=f;
limit-=f;
remain[i]-=f;
remain[i^1]+=f;
if (!limit) break;
}
}
return flow;
}
inline void dinic(int s,int t){
while (bfs(s,t))
maxflow+=dfs(s,t,inf);
}
int main(){
tot=-1;
memset(point,-1,sizeof(point));
memset(next,-1,sizeof(next));
scanf("%d%d",&m,&n);
for (int i=1;i<=m;++i){
scanf("%d%d%d",&x,&y,&cap);
add(x,y,cap);
}
dinic(1,n);
printf("%d\n",maxflow);
}
isap
// codevs 1993
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int max_n=205;
const int max_m=205;
const int max_e=max_m*2;
const int inf=1e9;
int point[max_n],next[max_e],v[max_e],remain[max_e],tot;
int cur[max_n],deep[max_n],last[max_n],num[max_n];
int n,m,x,y,cap,maxflow;
queue <int> q;
inline void add(int x,int y,int cap){
++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=cap;
++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0;
}
inline void bfs(int t){
for (int i=1;i<=n;++i)
deep[i]=n;
deep[t]=0;
for (int i=1;i<=n;++i)
cur[i]=point[i];
while (!q.empty()) q.pop();
q.push(t);
while (!q.empty()){
int now=q.front(); q.pop();
for (int i=point[now];i!=-1;i=next[i])
if (deep[v[i]]==n&&remain[i^1]){
deep[v[i]]=deep[now]+1;
q.push(v[i]);
}
}
}
inline int addflow(int s, int t) {
int ans=inf,now=t;
while (now!=s) {
ans=min(ans, remain[last[now]]);
now=v[last[now] ^ 1];
}
now=t;
while (now != s) {
remain[last[now]]-=ans;
remain[last[now]^1]+=ans;
now=v[last[now]^1];
}
return ans;
}
inline void isap(int s,int t){
int now=s;
bfs(t);
for (int i=1;i<=n;++i) ++num[deep[i]];
while (deep[s]<n){
if (now==t){
maxflow+=addflow(s,t);
now=s;
}
bool has_find=false;
for (int i=cur[now];i!=-1;i=next[i]){
int u=v[i];
if (deep[u]+1==deep[now]&&remain[i]){
has_find=true;
cur[now]=i;
last[u]=i;
now=u;
break;
}
}
if (!has_find){
int minn=n-1;
for (int i=point[now];i!=-1;i=next[i])
if (remain[i])
minn=min(minn,deep[v[i]]);
if (!(--num[deep[now]])) break;
num[deep[now]=minn+1]++;
cur[now]=point[now];
if (now!=s)
now=v[last[now]^1];
}
}
}
int main(){
tot=-1;
memset(point,-1,sizeof(point));
memset(next,-1,sizeof(next));
scanf("%d%d",&m,&n);
for (int i=1;i<=m;++i){
scanf("%d%d%d",&x,&y,&cap);
add(x,y,cap);
}
isap(1,n);
printf("%d\n",maxflow);
}
费用流
// codevs 1227
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int max_n=55;
const int max_N=max_n*max_n*2+5;
const int max_m=max_N*10;
const int max_e=max_m*2;
const int inf=1e9;
int n,k,N,cnt,val,x1,x2,y1,y2,maxflow,maxcost,sum;
int next[max_e],point[max_N],v[max_e],remain[max_e],c[max_e],tot;
int dis[max_N],last[max_N];
bool vis[max_N];
queue <int> q;
inline void addedge(int x,int y,int cap,int z){
++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=cap; c[tot]=z;
++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0; c[tot]=-z;
}
inline int addflow(int s,int t){
int ans=inf,now=t;
while (now!=s){
ans=min(ans,remain[last[now]]);
now=v[last[now]^1];
}
now=t;
while (now!=s){
remain[last[now]]-=ans;
remain[last[now]^1]+=ans;
now=v[last[now]^1];
}
return ans;
}
inline bool bfs(int s,int t){
memset(dis,128,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[s]=0;
vis[s]=true;
while (!q.empty()) q.pop();
q.push(s);
while (!q.empty()){
int now=q.front(); q.pop();
vis[now]=false;
for (int i=point[now];i!=-1;i=next[i])
if (dis[v[i]]<dis[now]+c[i]&&remain[i]){
dis[v[i]]=dis[now]+c[i];
last[v[i]]=i;
if (!vis[v[i]]){
vis[v[i]]=true;
q.push(v[i]);
}
}
}
if (dis[t]<0) return false;
int flow=addflow(s,t);
maxflow+=flow;
maxcost+=flow*dis[t];
return true;
}
inline void major(int s,int t){
maxflow=0; maxcost=0;
while (bfs(s,t));
}
int main(){
tot=-1;
memset(next,-1,sizeof(next));
memset(point,-1,sizeof(point));
scanf("%d%d",&n,&k);
N=n*n*2+2;
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j){
scanf("%d",&val);
cnt++;
x1=cnt*2; x2=cnt*2+1;
y1=(cnt+1)*2; y2=(cnt+n)*2;
addedge(x1,x2,1,val);
addedge(x1,x2,inf,0);
if (j!=n)
addedge(x2,y1,inf,0);
if (i!=n)
addedge(x2,y2,inf,0);
}
addedge(1,2,k,0);
addedge(N-1,N,k,0);
major(1,N);
printf("%d\n",maxcost);
}
匈牙利
// BZOJ 1854
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_n=1e6+5;
const int max_e=max_n*4;
int n,x,y,Max;
int tot,point[max_n],nxt[max_e],v[max_e];
int belong[max_n],vis[max_n];
inline void addedge(int x,int y)
{
++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
}
inline bool find(int x,int k)
{
for (int i=point[x];i;i=nxt[i])
if (vis[v[i]]!=k)
{
vis[v[i]]=k;
if (!belong[v[i]]||find(belong[v[i]],k))
{
belong[v[i]]=x;
return true;
}
}
return false;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;++i)
{
scanf("%d%d",&x,&y);
addedge(x,i); addedge(y,i);
Max=max(Max,x); Max=max(Max,y);
}
for (int i=1;i<=Max;++i)
if (!find(i,i))
{
printf("%d\n",i-1);
return 0;
}
printf("%d\n",Max);
}
tarjan
// hdu 1269
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_n=1e4+5;
const int max_m=1e5+5;
int n,m,x,y,N;
int tot,point[max_n],nxt[max_m*2],v[max_m*2];
int Dfn[max_n],Low[max_n],vis[max_n],strack[max_n],temp,cnt;
inline void clear(){
tot=0;memset(point,0,sizeof(point));memset(nxt,0,sizeof(nxt));memset(v,0,sizeof(v));
memset(Low,0,sizeof(Low)); memset(Dfn,0,sizeof(Dfn));
memset(strack,0,sizeof(strack)); temp=0;
memset(vis,0,sizeof(vis)); cnt=0;
}
inline void addedge(int x,int y){++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}
inline void tarjan(int now){
Dfn[now]=++N; strack[++temp]=now; vis[now]=1; Low[now]=Dfn[now];
for (int i=point[now];i;i=nxt[i])
if (!vis[v[i]]){
tarjan(v[i]);
Low[now]=min(Low[now],Low[v[i]]);
}
else Low[now]=min(Low[now],Dfn[v[i]]);
if (Low[now]==Dfn[now]){
++cnt;
while (strack[temp]!=now) vis[strack[temp]]=0,temp--;
vis[strack[temp]]=0,temp--;
}
}
int main(){
while (~scanf("%d%d",&n,&m)){
if (!n&&!m) return 0;
clear();
for (int i=1;i<=m;++i)
scanf("%d%d",&x,&y),addedge(x,y);
for (int i=1;i<=n;++i)
if (!vis[i]) tarjan(i);
if (cnt==1) printf("Yes\n");
else printf("No\n");
}
}
dijkstra堆优化
// hdu 1269
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_n=1e4+5;
const int max_m=1e5+5;
int n,m,x,y,N;
int tot,point[max_n],nxt[max_m*2],v[max_m*2];
int Dfn[max_n],Low[max_n],vis[max_n],strack[max_n],temp,cnt;
inline void clear(){
tot=0;memset(point,0,sizeof(point));memset(nxt,0,sizeof(nxt));memset(v,0,sizeof(v));
memset(Low,0,sizeof(Low)); memset(Dfn,0,sizeof(Dfn));
memset(strack,0,sizeof(strack)); temp=0;
memset(vis,0,sizeof(vis)); cnt=0;
}
inline void addedge(int x,int y){++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;}
inline void tarjan(int now){
Dfn[now]=++N; strack[++temp]=now; vis[now]=1; Low[now]=Dfn[now];
for (int i=point[now];i;i=nxt[i])
if (!vis[v[i]]){
tarjan(v[i]);
Low[now]=min(Low[now],Low[v[i]]);
}
else Low[now]=min(Low[now],Dfn[v[i]]);
if (Low[now]==Dfn[now]){
++cnt;
while (strack[temp]!=now) vis[strack[temp]]=0,temp--;
vis[strack[temp]]=0,temp--;
}
}
int main(){
while (~scanf("%d%d",&n,&m)){
if (!n&&!m) return 0;
clear();
for (int i=1;i<=m;++i)
scanf("%d%d",&x,&y),addedge(x,y);
for (int i=1;i<=n;++i)
if (!vis[i]) tarjan(i);
if (cnt==1) printf("Yes\n");
else printf("No\n");
}
}
KMP
// poj 3461
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_W=10005;
const int max_s=1000005;
char W[max_W],s[max_s];
int T[max_W];
int t,len_W,len_s,ans;
inline void calc_T(){
T[0]=-1;
int j;
for (int i=0;i<len_W;++i){
j=T[i];
while (j!=-1&&W[j]!=W[i])
j=T[j];
T[i+1]=++j;
}
}
inline void calc_ans(){
int j=0;
for (int i=0;i<len_s;++i){
while (j!=-1&&W[j]!=s[i])
j=T[j];
j++;
if (j==len_W){
ans++;
j=T[j];
}
}
}
int main(){
scanf("%d\n",&t);
while (t--){
gets(W);
gets(s);
len_W=strlen(W);
len_s=strlen(s);
memset(T,0,sizeof(T));
calc_T();
ans=0;
calc_ans();
printf("%d\n",ans);
}
}
AC自动机
// hdu 2222
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
const int max_n=1e4+5;
const int max_len=55;
const int max_ac=max_n*max_len;
const int max_s=1e6+5;
char s[max_s];
int T,n,ch[max_ac][30],fail[max_ac],tot,is_end[max_ac],ans;
bool vis[max_ac];
queue <int> q;
inline void clear(){
memset(ch,0,sizeof(ch));
memset(fail,0,sizeof(fail));
memset(is_end,0,sizeof(is_end));
memset(vis,0,sizeof(vis));
tot=0;
ans=0;
}
inline void insert(char s[]){
int len=strlen(s),now=0;
for (int i=0;i<len;++i){
int x=s[i]-'a';
if (!ch[now][x])
ch[now][x]=++tot;
now=ch[now][x];
}
is_end[now]++;
}
inline void make_fail(){
while (!q.empty()) q.pop();
for (int i=0;i<26;++i)
if (ch[0][i])
q.push(ch[0][i]);
while (!q.empty()){
int now=q.front(); q.pop();
for (int i=0;i<26;++i){
if (!ch[now][i]){
ch[now][i]=ch[fail[now]][i];
continue;
}
int x=ch[now][i];
fail[x]=ch[fail[now]][i];
q.push(x);
}
}
}
inline void AC(char s[]){
int len=strlen(s),now=0;
for (int i=0;i<len;++i){
vis[now]=true;
int x=s[i]-'a';
int m=ch[now][x];
while (m!=0&&!vis[m]){
vis[m]=true;
ans+=is_end[m];
is_end[m]=0;
m=fail[m];
}
now=ch[now][x];
}
}
int main(){
scanf("%d",&T);
while (T--){
clear();
scanf("%d",&n);
for (int i=1;i<=n;++i){
scanf("%s",s);
insert(s);
}
make_fail();
scanf("%s",s);
AC(s);
printf("%d\n",ans);
}
}
后缀数组
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxletter=255;
int n,m;
char s[1000];
int sa[1000],c[1000],x[1000],y[1000],height[1000],rank[1000];
inline int cmp(int a,int b,int k){
int x1=y[a],y1=y[b];
int x2=(a+k>n)?-1:y[a+k];
int y2=(b+k>n)?-1:y[b+k];
return x1==y1&&x2==y2;
}
inline void build_sa(){
m=maxletter;
for (int i=0;i<m;++i) c[i]=0;
for (int i=0;i<n;++i) c[x[i]=s[i]]++;
for (int i=1;i<m;++i) c[i]+=c[i-1];
for (int i=n-1;i>=0;--i) sa[--c[x[i]]]=i;
for (int k=1;k<=n;k<<=1){
int p=0;
for (int i=n-k;i<n;++i) y[p++]=i;
for (int i=0;i<n;++i) if (sa[i]>=k) y[p++]=sa[i]-k;
for (int i=0;i<m;++i) c[i]=0;
for (int i=0;i<n;++i) c[x[y[i]]]++;
for (int i=1;i<m;++i) c[i]+=c[i-1];
for (int i=n-1;i>=0;--i) sa[--c[x[y[i]]]]=y[i];
swap(x,y);
p=1; x[sa[0]]=0;
for (int i=1;i<n;++i)
x[sa[i]]=cmp(sa[i],sa[i-1],k)?p-1:p++;
if (p>=n) break;
m=p;
}
}
inline void build_lcp(){
for (int i=0;i<n;++i) rank[sa[i]]=i;
height[0]=0;
int k=0;
for (int i=0;i<n;++i){
if (k) --k;
int j=sa[rank[i]-1];
while (s[i+k]==s[j+k]) k++;
height[rank[i]]=k;
}
}
int main(){
gets(s);
n=strlen(s);
build_sa();
build_lcp();
for (int i=0;i<n;++i) printf("%d%c",sa[i]," \n"[i==n-1]);
for (int i=0;i<n;++i) printf("%d%c",height[i]," \n"[i==n-1]);
}
左偏树
//BZOJ 1455
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int max_n=1e6+5;
const int max_m=1e5+5;
int n,m,x,y,fx,fy,top;
int f[max_n],lst[max_n],rst[max_n],disst[max_n],keyst[max_n]; char opt;
bool have_killed[max_n];
inline int find(int x){if (x==f[x]) return x;else return f[x]=find(f[x]);}
inline int merge(int x,int y){
if (!x) return y;
if (!y) return x;
if (keyst[x]>keyst[y]) swap(x,y);
rst[x]=merge(rst[x],y);
if (disst[rst[x]]>disst[lst[x]]) swap(rst[x],lst[x]);
disst[x]=disst[rst[x]]+1;
return x;
}
inline void pop(int x){
f[x]=merge(lst[x],rst[x]);
f[f[x]]=f[x];
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;++i) scanf("%d",&keyst[i]),f[i]=i;
scanf("%d",&m);
for (int i=1;i<=m;++i){
opt=getchar();
while (opt!='M'&&opt!='K') opt=getchar();
if (opt=='M')
{
scanf("%d%d",&x,&y);
if (have_killed[x]||have_killed[y]) continue;
fx=find(x),fy=find(y);
if (fx!=fy)
top=merge(fx,fy),f[fx]=f[fy]=top;
}
else
{
scanf("%d",&x);
if (have_killed[x]) {printf("0\n");continue;}
fx=find(x); have_killed[fx]=true; printf("%d\n",keyst[fx]);
pop(fx);
}
}
}