[置顶] 模板

线段树

//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);
        }
    }
}

你可能感兴趣的:(模板)