我的模板库【填坑中】

来源:互联网 发布:app无网络提示 编辑:程序博客网 时间:2024/05/22 06:58

字符串

  • AC自动机
  • manacher

【APIO2014】uoj103 Palindromes【2017.7.12】

#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int maxn=600010;#define LL long longchar s[maxn];int trans[maxn][30],fail[maxn],val[maxn],cnt[maxn],ord[maxn],mxl[maxn],num[maxn],fa[maxn][20],pos[maxn],n,tot=1;int main(){    //int xxx=0;    //freopen("b.in","r",stdin);    //freopen("b.out","w",stdout);    LL ans=0;    int last=1,u,nu,v,nv,x,y,lim=0,mx,id;    scanf("%s",s+1);    n=strlen(s+1);    for (int i=1;i<=n;i++)    {        x=s[i]-'a'+1;        u=last;        val[last=nu=++tot]=i;        while (u&&!trans[u][x])        {            trans[u][x]=nu;            u=fail[u];        }        if (!u) fail[nu]=1;        else        {            v=trans[u][x];            if (val[v]==val[u]+1) fail[nu]=v;            else            {                val[nv=++tot]=val[u]+1;                fail[nv]=fail[v];                fail[v]=fail[nu]=nv;                for (int j=1;j<=26;j++) trans[nv][j]=trans[v][j];                while (u&&trans[u][x]==v)                {                    trans[u][x]=nv;                    u=fail[u];                }            }        }    }    pos[0]=1;    for (int i=1;i<=n;i++) num[pos[i]=trans[pos[i-1]][s[i]-'a'+1]]++;    for (int i=1;i<=tot;i++) cnt[val[i]]++;    for (int i=1;i<=n;i++) cnt[i]+=cnt[i-1];    for (int i=1;i<=tot;i++) ord[cnt[val[i]]--]=i;    for (int i=tot;i>=1;i--) num[fail[ord[i]]]+=num[ord[i]];    while ((1<<lim)<tot) lim++;    for (int i=1;i<=tot;i++) fa[i][0]=fail[i];    for (int k=1;k<=lim;k++)        for (int i=1;i<=tot;i++)            fa[i][k]=fa[fa[i][k-1]][k-1];    for (int i=n*2+1;i>=1;i--) s[i]=(i&1)?'$':s[i/2];    s[0]='@';    s[2*n+2]='%';    mx=0;    for (int i=1;i<=2*n+1;i++)    {        if (i<=mx) mxl[i]=min(mxl[2*id-i],mx-i);        //printf("%d:%d,%d,%d\n",i,id,mx,mxl[i]);        while (s[i-mxl[i]-1]==s[i+mxl[i]+1])        {            mxl[i]++;            //xxx++;        }        if (i+mxl[i]>mx)        {            for (int j=mx;j<=i+mxl[i];j+=2)            {                x=j/2;                y=(2*i-j)/2+1;                u=pos[x];                for (int k=lim;k>=0;k--)                    if (val[fa[u][k]]>=x-y+1) u=fa[u][k];                ans=max(ans,(LL)num[u]*(x-y+1));            }            mx=i+mxl[i];            id=i;        }    }    //printf("%d\n",xxx);    printf("%lld\n",ans);}
  • 后缀数组
    poj1743 Musical Theme【2017.4.21】
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int c=90,maxn=30010,oo=0x3f3f3f3f;int a[maxn],sa[maxn],rank[maxn],height[maxn],f[maxn],cnt[maxn],n;void solve(){    int m,p,l,r,mid,ok,mnp,mxp;    memset(a,0,sizeof(a));    for (int i=1;i<=n;i++) scanf("%d",&a[i]);    for (int i=1;i<n;i++) a[i]=a[i+1]-a[i]+c;    a[n]=0;    m=190;    for (int i=1;i<=m;i++) cnt[i]=0;    for (int i=1;i<n;i++) cnt[rank[i]=a[i]]++;    for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];    for (int i=n-1;i;i--) sa[cnt[a[i]]--]=i;    for (int k=1;k<n;k<<=1)    {        p=0;        for (int i=n-k;i<n;i++) f[++p]=i;        for (int i=1;i<n;i++) if (sa[i]-k>=1) f[++p]=sa[i]-k;        for (int i=1;i<=m;i++) cnt[i]=0;        for (int i=1;i<n;i++) cnt[rank[f[i]]]++;        for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];        for (int i=n-1;i;i--) sa[cnt[rank[f[i]]]--]=f[i];        for (int i=1;i<n;i++) f[i]=rank[i];        rank[sa[1]]=1;        for (int i=2;i<n;i++)            if (f[sa[i]]!=f[sa[i-1]]||f[sa[i]+k]!=f[sa[i-1]+k])                rank[sa[i]]=rank[sa[i-1]]+1;            else                rank[sa[i]]=rank[sa[i-1]];        m=rank[sa[n-1]];        if (m>=n-1) break;    }    for (int i=1;i<n;i++)    {        height[rank[i]]=height[rank[i-1]];        if (height[rank[i]]) height[rank[i]]--;        while (a[i+height[rank[i]]]==a[sa[rank[i]-1]+height[rank[i]]]) height[rank[i]]++;    }    l=0;    r=n-1;    while (l<r)    {        mid=l+r+1>>1;        ok=0;        for (int i=1;i<n&&!ok;i++)            if (height[i]>=mid)            {                mxp=max(mxp,sa[i]);                mnp=min(mnp,sa[i]);                if (mxp-mnp>mid) ok=1;            }            else mxp=mnp=sa[i];        if (ok) l=mid;        else r=mid-1;    }    //printf("%d\n",l+1);    if (l>=4) printf("%d\n",l+1);    else printf("0\n");}int main(){    while (scanf("%d",&n)&&n) solve();}

poj2774 Long Long Message【2017.5.17】

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=400010;char s[maxn];int sa[maxn],rank[maxn],height[maxn],f[maxn],g[maxn],cnt[maxn];int main(){    int n,m=27,l,p,ans=0;    scanf("%s",s+1);    l=strlen(s+1);    s[l+1]='z'+1;    scanf("%s",s+l+2);    n=strlen(s+1);    for (int i=1;i<=n;i++) cnt[rank[i]=s[i]-'a'+1]++;    for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];    for (int i=n;i;i--) sa[cnt[rank[i]]--]=i;    for (int k=1;;k<<=1)    {        p=0;        for (int i=n-k+1;i<=n;i++) f[++p]=i;        for (int i=1;i<=n;i++)            if (sa[i]>k) f[++p]=sa[i]-k;        for (int i=1;i<=m;i++) cnt[i]=0;        for (int i=1;i<=n;i++) cnt[rank[f[i]]]++;        for (int i=1;i<=m;i++) cnt[i]+=cnt[i-1];        for (int i=n;i;i--) sa[cnt[rank[f[i]]]--]=f[i];        for (int i=1;i<=n;i++) g[i]=rank[i];        rank[sa[1]]=1;        for (int i=2;i<=n;i++)            rank[sa[i]]=rank[sa[i-1]]+(g[sa[i]]!=g[sa[i-1]]||g[sa[i]+k]!=g[sa[i-1]+k]);        m=rank[sa[n]];        if (m>=n) break;    }    for (int i=1;i<=n;i++)    {        height[rank[i]]=height[rank[i-1]];        if (height[rank[i]]) height[rank[i]]--;        while (s[i+height[rank[i]]]==s[sa[rank[i]-1]+height[rank[i]]]) height[rank[i]]++;    }    for (int i=2;i<=n;i++)        if ((sa[i]<=l&&sa[i-1]>=l+2)||(sa[i]>=l+2&&sa[i-1]<=l))            ans=max(ans,height[i]);    printf("%d\n",ans);}
  • 后缀自动机
    SPOJ NSUBSTR Substrings【2017.4.21】
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=500010;char s[maxn];int fail[maxn],val[maxn],trans[maxn][30],cnt[maxn],f[maxn],num[maxn],ans[maxn],n,tot=1;int main(){    int p,last=1,x,np,q,nq;    scanf("%s",s+1);    n=strlen(s+1);    for (int i=1;i<=n;i++)    {        x=s[i]-'a';        p=last;        val[last=np=++tot]=val[p]+1;        while (p&&!trans[p][x])        {            trans[p][x]=np;            p=fail[p];        }        if (!p) fail[np]=1;        else        {            q=trans[p][x];            if (val[q]==val[p]+1) fail[np]=q;            else            {                val[nq=++tot]=val[p]+1;                fail[nq]=fail[q];                fail[q]=fail[np]=nq;                for (int j=0;j<26;j++) trans[nq][j]=trans[q][j];                while (p&&trans[p][x]==q)                {                    trans[p][x]=nq;                    p=fail[p];                }            }        }    }    p=1;    for (int i=1;i<=n;i++)    {        p=trans[p][s[i]-'a'];        cnt[p]++;    }    for (int i=1;i<=tot;i++) num[val[i]]++;    for (int i=n-1;i;i--) num[i]+=num[i+1];    for (int i=1;i<=tot;i++) f[num[val[i]]--]=i;    for (int i=1;i<=tot;i++)    {        cnt[fail[f[i]]]+=cnt[f[i]];        ans[val[f[i]]]=max(ans[val[f[i]]],cnt[f[i]]);    }    for (int i=n-1;i;i--) ans[i]=max(ans[i],ans[i+1]);    for (int i=1;i<=n;i++) printf("%d\n",ans[i]);}

poj2774 Long Long Message【2017.5.17】

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int maxn=200010;char s1[maxn],s2[maxn];int trans[maxn][30],fail[maxn],val[maxn],n,m,tot=1;int main(){    int last=1,x,p,q,np,nq,now=0,ans=0;    scanf("%s",s1+1);    n=strlen(s1+1);    for (int i=1;i<=n;i++)    {        x=s1[i]-'a'+1;        p=last;        val[last=np=++tot]=val[p]+1;        while (p&&!trans[p][x])        {            trans[p][x]=np;            p=fail[p];        }        if (!p) fail[np]=1;        else        {            q=trans[p][x];            if (val[q]==val[p]+1) fail[np]=q;            else            {                val[nq=++tot]=val[p]+1;                fail[nq]=fail[q];                fail[q]=fail[np]=nq;                for (int j=1;j<=26;j++) trans[nq][j]=trans[q][j];                while (p&&trans[p][x]==q)                {                    trans[p][x]=nq;                    p=fail[p];                }            }        }    }    scanf("%s",s2+1);    m=strlen(s2+1);    p=1;    for (int i=1;i<=m;i++)    {        x=s2[i]-'a'+1;        if (trans[p][x])        {            p=trans[p][x];            now++;        }        else        {            while (p&&!trans[p][x]) p=fail[p];            if (p)            {                now=val[p]+1;                p=trans[p][x];            }            else            {                now=0;                p=1;            }        }        ans=max(ans,now);    }    printf("%d\n",ans);}
  • 回文自动机
    【APIO2014】bzoj3676 回文串
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define LL long longconst int maxn=600010;char s[maxn];int val[maxn],fail[maxn],trans[maxn][30],cnt[maxn],num[maxn],f[maxn],n;int main(){    int tot=1,last=0,p,np,x,q;    LL ans=0;    scanf("%s",s+1);    n=strlen(s+1);    fail[0]=fail[1]=1;    val[1]=-1;    for (int i=1;i<=n;i++)    {        x=s[i]-'a';        p=last;        while (s[i-val[p]-1]!=s[i]) p=fail[p];        if (!trans[p][x])        {            val[np=++tot]=val[p]+2;            q=fail[p];            while (s[i-val[q]-1]!=s[i]) q=fail[q];            fail[np]=trans[q][x];            trans[p][x]=np;        }        cnt[last=trans[p][x]]++;    }    for (int i=2;i<=tot;i++) num[val[i]]++;    for (int i=1;i<=n;i++) num[i]+=num[i-1];    for (int i=2;i<=tot;i++) f[num[val[i]]--]=i;    for (int i=tot-1;i;i--)    {        ans=max(ans,(LL)val[f[i]]*cnt[f[i]]);        cnt[fail[f[i]]]+=cnt[f[i]];    }    printf("%lld\n",ans);}

树形数据结构

  • treap
    bzoj3224 普通平衡树【2017.4.17】
#include<cstdio>#include<algorithm>using namespace std;const int maxn=100010,no=2e9+100;int rd(){    int x=0,f=1;    char c=getchar();    while (c<'0'||c>'9')    {        if (c=='-') f=-1;        c=getchar();    }    while (c>='0'&&c<='9')    {        x=x*10+c-'0';        c=getchar();    }    return x*f;}struct treap{    int son[2][maxn],v[maxn],w[maxn],siz[maxn],cnt[maxn],rt,tot;    void upd(int p)    {        siz[p]=siz[son[0][p]]+siz[son[1][p]]+cnt[p];    }    void rot(int &p,int fl)    {        int u=son[fl][p],v=son[fl^1][u];        son[fl][p]=v;        son[fl^1][u]=p;        upd(p);        p=u;        upd(p);    }    void ins(int &p,int x)    {        if (!p)        {            p=++tot;            v[p]=x;            w[p]=rand();            siz[p]=cnt[p]=1;            return;        }        siz[p]++;        if (v[p]==x)        {            cnt[p]++;            return;        }        int flag=x>v[p];        ins(son[flag][p],x);        if (w[son[flag][p]]>w[p]) rot(p,flag);    }    void del(int &p,int x)    {        if (v[p]==x)        {            if (son[0][p]*son[1][p]==0)            {                cnt[p]--;                siz[p]--;                if (!cnt[p]) p=son[0][p]+son[1][p];            }            else            {                int fl=w[son[0][p]]<w[son[1][p]];                rot(p,fl);                siz[p]--;                del(son[fl^1][p],x);            }            return;        }        siz[p]--;        del(son[x>v[p]][p],x);    }    int rank(int p,int x)    {        if (v[p]==x) return siz[son[0][p]]+1;        if (x<v[p]) return rank(son[0][p],x);        return siz[son[0][p]]+cnt[p]+rank(son[1][p],x);    }    int qry(int p,int x)    {        if (x<=siz[son[0][p]]) return qry(son[0][p],x);        if (x<=siz[son[0][p]]+cnt[p]) return v[p];        return qry(son[1][p],x-(siz[son[0][p]]+cnt[p]));    }    int pre(int p,int x)    {        if (!p) return no;        if (v[p]<x)        {            int y=pre(son[1][p],x);            return y==no?v[p]:y;        }        return pre(son[0][p],x);    }    int suc(int p,int x)    {        if (!p) return no;        if (v[p]>x)        {            int y=suc(son[0][p],x);            return y==no?v[p]:y;        }        return suc(son[1][p],x);    }    void Ins(int x)    {        ins(rt,x);    }    void Del(int x)    {        del(rt,x);    }    int Rank(int x)    {        return rank(rt,x);    }    int Qry(int x)    {        return qry(rt,x);    }    int Pre(int x)    {        return pre(rt,x);    }    int Suc(int x)    {        return suc(rt,x);    }}t;int main(){    int n,opt;    n=rd();    while (n--)    {        opt=rd();        switch (opt)        {            case 1:t.Ins(rd());break;            case 2:t.Del(rd());break;            case 3:printf("%d\n",t.Rank(rd()));break;            case 4:printf("%d\n",t.Qry(rd()));break;            case 5:printf("%d\n",t.Pre(rd()));break;            case 6:printf("%d\n",t.Suc(rd()));break;        }    }}
  • splay
    bzoj3224 普通平衡树【2017.4.17】
#include<cstdio>#include<algorithm>using namespace std;const int maxn=100010,no=2e9+1000;int rd(){    int x=0,f=1;    char c=getchar();    while (c<'0'||c>'9')    {        if (c=='-') f=-1;        c=getchar();    }    while (c>='0'&&c<='9')    {        x=x*10+c-'0';        c=getchar();    }    return x*f;}int fa[maxn],son[maxn][2],v[maxn],cnt[maxn],siz[maxn],tot,rt;void pause(){    int x=0;    x=1;}void upd(int p){    siz[p]=siz[son[p][0]]+siz[son[p][1]]+cnt[p];}void rot(int p,int fl){    int u=son[p][fl],v=son[u][fl^1];    fa[u]=fa[p];    if (!fa[u]) rt=u;    else son[fa[u]][son[fa[u]][1]==p]=u;    son[p][fl]=v;    if (v) fa[v]=p;    son[u][fl^1]=p;    fa[p]=u;    upd(p);    upd(u);}void splay(int u){    int v,x,w,y;    upd(u);    while (rt!=u)    {        v=fa[u];        x=son[v][1]==u;        if (v==rt) rot(v,x);        else        {            w=fa[v];            y=son[w][1]==v;            if (x==y) rot(w,y),rot(v,x);            else rot(v,x),rot(w,y);        }    }}void ins(int p,int x,int f,int fl){    if (!p)    {        p=++tot;        cnt[p]=1;        v[p]=x;        if (f)        {            fa[p]=f;            son[f][fl]=p;        }        else rt=p;        splay(p);        return;    }    if (x==v[p])    {        cnt[p]++;        splay(p);        return;    }    int fl2=x>v[p];    ins(son[p][fl2],x,p,fl2);}void del(int p,int x,int f,int fl){    if (v[p]==x)    {        if (cnt[p]>1)        {            cnt[p]--;            splay(p);        }        else        {            if (son[p][0]*son[p][1]==0)            {                if (f)                {                    son[f][fl]=son[p][0]+son[p][1];                    if (son[f][fl])                    {                        fa[son[f][fl]]=f;                        splay(son[f][fl]);                    }                    else splay(f);                }                else fa[rt=son[p][0]+son[p][1]]=0;            }            else            {                int fl2=siz[son[p][0]]<siz[son[p][1]];                rot(p,fl2);                del(p,x,fa[p],fl2^1);            }        }    }    else    {        int fl2=x>v[p];        del(son[p][fl2],x,p,fl2);    }}int rank(int p,int x){    if (x==v[p])    {        splay(p);        return siz[son[p][0]]+1;    }    if (x<v[p]) return rank(son[p][0],x);    return rank(son[p][1],x);}int qry(int p,int x){    if (x<=siz[son[p][0]]) return qry(son[p][0],x);    if (x<=siz[son[p][0]]+cnt[p])    {        splay(p);        return v[p];    }    return qry(son[p][1],x-siz[son[p][0]]-cnt[p]);}int pre(int p,int x){    if (!p) return no;    if (v[p]<x)    {        int y=pre(son[p][1],x);        if (y==no)        {            splay(p);            return v[p];        }        return y;    }    return pre(son[p][0],x);}int suc(int p,int x){    if (!p) return no;    if (v[p]>x)    {        int y=suc(son[p][0],x);        if (y==no)        {            splay(p);            return v[p];        }        return y;    }    return suc(son[p][1],x);}int main(){    /*freopen("phs.in","r",stdin);    freopen("phs.out","w",stdout);*/    int n,opt;    n=rd();    while (n--)    {        if (n==1) pause();         opt=rd();        switch (opt)        {            case 1:ins(rt,rd(),0,0);break;            case 2:del(rt,rd(),0,0);break;            case 3:printf("%d\n",rank(rt,rd()));break;            case 4:printf("%d\n",qry(rt,rd()));break;            case 5:printf("%d\n",pre(rt,rd()));break;            case 6:printf("%d\n",suc(rt,rd()));break;        }    }}

【AHOI2006】bzoj1269 文本编辑器【2017.4.19】

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define rt son[1][0]const int maxn=4000010;char s[maxn],s1[maxn],chr[maxn];int fa[maxn],son[maxn][2],inv[maxn],size[maxn],tot=3;void down(int u){    if (inv[u])    {        swap(son[u][0],son[u][1]);        if (son[u][0]) inv[son[u][0]]^=1;        if (son[u][1]) inv[son[u][1]]^=1;        inv[u]=0;    }}void upd(int u){    size[u]=size[son[u][0]]+size[son[u][1]]+1;}int find(int u,int p){    down(u);    if (p<=size[son[u][0]]) return find(son[u][0],p);    if (p==size[son[u][0]]+1) return u;    return find(son[u][1],p-size[son[u][0]]-1);}void rot(int u,int f){    int v=son[u][f],w=son[v][f^1],x=fa[u],fx=son[x][1]==u;    son[u][f]=w;    if (w) fa[w]=u;    son[v][f^1]=u;    fa[u]=v;    son[x][fx]=v;    fa[v]=x;    upd(u);    upd(v);}void get(int p,int f){    int u=find(rt,p),x,y,fx,fy;    while (fa[u]!=f)    {        x=fa[u];        fx=son[x][1]==u;        y=fa[x];        fy=son[y][1]==x;        if (y==f) rot(x,fx);        else        {            if (fx==fy) rot(y,fy),rot(x,fx);            else rot(x,fx),rot(y,fy);        }    }}int build(int l,int r){    if (l>r) return 0;    int mid=l+r>>1,ret;    chr[ret=++tot]=s[mid];    son[ret][0]=build(l,mid-1);    if (son[ret][0]) fa[son[ret][0]]=ret;    son[ret][1]=build(mid+1,r);    if (son[ret][1]) fa[son[ret][1]]=ret;    upd(ret);    return ret;}int main(){    int m,n,p=1;    scanf("%d",&m);    son[1][0]=2;    son[2][0]=3;    fa[2]=1;    fa[3]=2;    size[2]=2;    size[3]=1;    while (m--)    {        scanf("%s",s1);        switch (s1[0])        {            case 'M':scanf("%d",&p);p++;break;            case 'I':                scanf("%d",&n);                gets(s+1);                gets(s+1);                get(p,1);                get(p+1,rt);                son[son[rt][1]][0]=build(1,n);                fa[son[son[rt][1]][0]]=son[rt][1];                upd(son[rt][1]);                upd(rt);                break;            case 'D':                scanf("%d",&n);                get(p,1);                get(p+n+1,rt);                son[son[rt][1]][0]=0;                upd(son[rt][1]);                upd(rt);                break;            case 'R':                scanf("%d",&n);                get(p,1);                get(p+n+1,rt);                inv[son[son[rt][1]][0]]^=1;                break;            case 'G':                get(p+1,1);                printf("%c\n",chr[rt]);                break;            case 'P':p--;break;            case 'N':p++;break;        }    }}
  • 替罪羊树
  • kdtree
    bzoj2648 SJY摆棋子【2017.4.21】
#include<cstdio>#include<algorithm>using namespace std;#define R(k) for (int k=0;k<2;k++)const int maxn=2000010,oo=0x3f3f3f3f;int D,ans;struct Point{    int x[2];    void rd()    {        R(k) scanf("%d",&x[k]);    }    bool operator < (const Point &p) const    {        return x[D]<p.x[D];    }}a[maxn],p;int lson[maxn],rson[maxn],mx[maxn][2],mn[maxn][2],tot,rt;void upd(int p){    R(k)    {        mx[p][k]=mn[p][k]=a[p].x[k];        if (lson[p])        {            mx[p][k]=max(mx[p][k],mx[lson[p]][k]);            mn[p][k]=min(mn[p][k],mn[lson[p]][k]);        }        if (rson[p])        {            mx[p][k]=max(mx[p][k],mx[rson[p]][k]);            mn[p][k]=min(mn[p][k],mn[rson[p]][k]);        }    }}int build(int L,int R,int d){    if (L>R) return 0;    int mid=L+R>>1;    D=d;    nth_element(a+L,a+mid,a+R+1);    lson[mid]=build(L,mid-1,d^1);    rson[mid]=build(mid+1,R,d^1);    upd(mid);    return mid;}void ins(int &u,int d){    if (!u)    {        a[u=++tot]=p;        R(k) mn[u][k]=mx[u][k]=p.x[k];        return;    }    if (p.x[d]<a[u].x[d]) ins(lson[u],d^1);    else ins(rson[u],d^1);    upd(u);}int mindis(int u){    if (!u) return oo;    int ret=0;    R(k)    {        if (mn[u][k]>p.x[k]) ret+=mn[u][k]-p.x[k];        if (mx[u][k]<p.x[k]) ret+=p.x[k]-mx[u][k];    }    return ret;}void qry(int u,int d){    int ret=0,lmn=mindis(lson[u]),rmn=mindis(rson[u]);    R(k) ret+=abs(p.x[k]-a[u].x[k]);    ans=min(ans,ret);    if (lmn<rmn)    {        if (lmn<ans) qry(lson[u],d^1);        if (rmn<ans) qry(rson[u],d^1);    }    else    {        if (rmn<ans) qry(rson[u],d^1);        if (lmn<ans) qry(lson[u],d^1);    }}int main(){    int n,m,opt;    scanf("%d%d",&n,&m);    for (int i=1;i<=n;i++) a[i].rd();    rt=build(1,n,0);    tot=n;    while (m--)    {        scanf("%d",&opt);        R(k) scanf("%d",&p.x[k]);        if (opt==1) ins(rt,0);        else        {            ans=oo;            qry(rt,0);            printf("%d\n",ans);        }    }}
  • 左偏树
  • 主席树
    poj2104 K-th Number【2017.5.16】
#include<cstdio>#include<algorithm>using namespace std;const int maxn=2000010;int rd(){    int x=0,f=1;    char c=getchar();    while (c<'0'||c>'9')    {        if (c=='-') f=-1;        c=getchar();    }    while (c>='0'&&c<='9')    {        x=x*10+c-'0';        c=getchar();    }    return x*f;}int a[maxn],ord[maxn],rt[maxn],sum[maxn],lson[maxn],rson[maxn],n,tot;int modi(int bro,int L,int R,int x){    int u=++tot;    sum[tot]=sum[bro]+1;    if (L==R) return u;    int mid=(L+R)/2;    if (x<=mid)    {        lson[u]=modi(lson[bro],L,mid,x);        rson[u]=rson[bro];    }    else    {        lson[u]=lson[bro];        rson[u]=modi(rson[bro],mid+1,R,x);    }    return u;}int qry(int u,int v,int L,int R,int k){    if (L==R) return L;    int mid=(L+R)/2;    if (k<=sum[lson[u]]-sum[lson[v]]) return qry(lson[u],lson[v],L,mid,k);    return qry(rson[u],rson[v],mid+1,R,k-(sum[lson[u]]-sum[lson[v]]));}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int m,q,l,r,k;    n=rd();    q=rd();    for (int i=1;i<=n;i++) ord[i]=a[i]=rd();    sort(ord+1,ord+n+1);    m=unique(ord+1,ord+n+1)-ord-1;    for (int i=1;i<=n;i++) a[i]=lower_bound(ord+1,ord+m+1,a[i])-ord;    for (int i=1;i<=n;i++) rt[i]=modi(rt[i-1],1,m,a[i]);    while (q--)    {        l=rd();        r=rd();        k=rd();        printf("%d\n",ord[qry(rt[r],rt[l-1],1,m,k)]);    }}

数论

  • 中国剩余定理
  • 离散对数

bzoj4128 Matrix【2017.5.18】

#include<cstdio>#include<cmath>#include<map>#include<algorithm>using namespace std;#define LL unsigned long longconst int maxn=75,r=131;int n,p,m;map<LL,int> mp;int inc(int x,int y){    x+=y;return x>=p?x-p:x;}int dec(int x,int y){    x-=y;return x<0?x+p:x;}int inverse(int x){    int ret=1;    for (int k=p-2;k;k>>=1,x=x*x%p)        if (k&1) ret=ret*x%p;    return ret;}struct mat{    int a[maxn][maxn];    LL h;    void get()    {        h=0;        for (int i=1;i<=n;i++)            for (int j=1;j<=n;j++)                h=h*r+a[i][j];    }    void rd()    {        for (int i=1;i<=n;i++)            for (int j=1;j<=n;j++)                scanf("%d",&a[i][j]);        get();    }    void init()    {        for (int i=1;i<=n;i++)            for (int j=1;j<=n;j++)                a[i][j]=(i==j);        get();    }    mat operator * (const mat &m) const    {        mat ret;        for (int i=1;i<=n;i++)            for (int j=1;j<=n;j++)            {                ret.a[i][j]=0;                for (int k=1;k<=n;k++)                    ret.a[i][j]=inc(ret.a[i][j],a[i][k]*m.a[k][j]%p);            }        ret.get();        return ret;    }    mat inv()    {        mat ret;        int x,t;        ret.init();        for (int i=1;i<=n;i++)        {            x=0;            for (int j=i;j<=n;j++)                if (a[j][i])                {                    x=j;                    break;                }            if (x!=i)                for (int j=1;j<=n;j++)                {                    swap(a[i][j],a[x][j]);                    swap(ret.a[i][j],ret.a[x][j]);                }            t=inverse(a[i][i]);            for (int j=1;j<=n;j++)            {                a[i][j]=a[i][j]*t%p;                ret.a[i][j]=ret.a[i][j]*t%p;            }            for (int j=1;j<=n;j++)                if (j!=i)                {                    t=a[j][i];                    for (int k=1;k<=n;k++)                    {                        a[j][k]=dec(a[j][k],a[i][k]*t%p);                        ret.a[j][k]=dec(ret.a[j][k],ret.a[i][k]*t%p);                    }                }        }        ret.get();        return ret;    }}a,b,c;int main(){    scanf("%d%d",&n,&p);    a.rd();    b.rd();    m=sqrt(p);    c.init();    for (int i=0;i<m;i++)    {        if (!mp.count(c.h)) mp[c.h]=i;        c=c*a;        if (b.h==c.h)        {            printf("%d\n",i+1);            return 0;        }    }    c=c.inv();    for (int i=1;;i++)    {        b=b*c;        if (mp.count(b.h))        {            printf("%d\n",i*m+mp[b.h]);            return 0;        }    }}
  • 杜教筛

bzoj3944 Sum【2017.7.14】

#include<cstdio>#include<algorithm>using namespace std;#define LL long longconst int maxn=2000000,p=2333333;int prm[maxn+5],fir[p+5],ne[p+5],val[p+5],tot,num;LL phi[maxn+5],mu[maxn+5],ansphi[p+5],ansmu[p+5];int find(int n,LL &resphi,LL &resmu){    for (int i=fir[n%p];i;i=ne[i])        if (val[i]==n)        {            resphi=ansphi[i];            resmu=ansmu[i];            return 1;        }    return 0;}void ins(int n,LL resphi,LL resmu){    if (tot>p) return;    int x=n%p;    tot++;    ne[tot]=fir[x];    fir[x]=tot;    val[tot]=n;    ansphi[tot]=resphi;    ansmu[tot]=resmu;}void solve(int n,LL &resphi,LL &resmu){    if (n<=maxn)    {        resphi=phi[n];        resmu=mu[n];        return;    }    if (find(n,resphi,resmu)) return;    LL tphi,tmu;    resphi=n*(n+1LL)/2;    resmu=1;    for (unsigned int i=2,j;i<=n;i=j+1)    {        j=n/(n/i);        solve(n/i,tphi,tmu);        resphi-=(j-i+1)*tphi;        resmu-=(j-i+1)*tmu;    }    ins(n,resphi,resmu);}int main(){    //freopen("a.in","r",stdin);    int n;    LL resphi,resmu;    mu[1]=phi[1]=1;    for (int i=2;i<=maxn;i++)    {        if (!phi[i])        {            prm[++num]=i;            phi[i]=i-1;            mu[i]=-1;        }        for (int j=1;j<=num&&(LL)i*prm[j]<=maxn;j++)            if (i%prm[j])            {                mu[i*prm[j]]=-mu[i];                phi[i*prm[j]]=phi[i]*(prm[j]-1);            }            else            {                mu[i*prm[j]]=0;                phi[i*prm[j]]=phi[i]*prm[j];                break;            }        phi[i]+=phi[i-1];        mu[i]+=mu[i-1];    }    int T;    scanf("%d",&T);    while (T--)    {        scanf("%d",&n);        solve(n,resphi,resmu);        printf("%lld %lld\n",resphi,resmu);    }}

bzoj4916神犇和蒟蒻【2017.7.15】

#include<cstdio>#include<algorithm>using namespace std;#define LL long longconst int p=1000000007,maxn=1000000,mod=2333333;int inc(int x,int y){    x+=y;    return x>=p?x-p:x;}int dec(int x,int y){    x-=y;    return x<0?x+p:x;}int prm[maxn+10],phi[maxn+10],fir[mod+10],ne[mod+10],val[mod+10],ans[mod+10],tot,num;int sum1(int n){    return (LL)n*(n+1)/2%p;}int sum2(int n){    int x=n,y=n+1,z=2*n+1;    if (x%2==0) x/=2;    else y/=2;    if (x%3==0) x/=3;    else if (y%3==0) y/=3;    else z/=3;    return (LL)x*y%p*z%p;}int find(int n,int &ret){    for (int i=fir[n%mod];i;i=ne[i])        if (val[i]==n)        {            ret=ans[i];            return 1;        }    return 0;}void ins(int n,int ret){    if (tot>mod) return;    int x=n%mod;    tot++;    ne[tot]=fir[x];    fir[x]=tot;    val[tot]=n;    ans[tot]=ret;}int solve(int n){    if (n<=maxn) return phi[n];    int ret;    if (find(n,ret)) return ret;    ret=sum2(n);    for (int i=2,j;i<=n;i=j+1)    {        j=n/(n/i);        ret=dec(ret,(LL)dec(sum1(j),sum1(i-1))*solve(n/i)%p);    }    ins(n,ret);    return ret;}int main(){    phi[1]=1;    for (int i=2;i<=maxn;i++)    {        if (!phi[i])        {            prm[++num]=i;            phi[i]=i-1;        }        for (int j=1;j<=num&&(LL)i*prm[j]<=maxn;j++)            if (i%prm[j]) phi[i*prm[j]]=phi[i]*(prm[j]-1);            else            {                phi[i*prm[j]]=phi[i]*prm[j];                break;            }        phi[i]=inc(phi[i-1],(LL)i*phi[i]%p);    }    int n;    scanf("%d",&n);    printf("1\n%d\n",solve(n));}

高等数学

  • 矩阵求逆

bzoj4128 Matrix【2017.5.18】

#include<cstdio>#include<cmath>#include<map>#include<algorithm>using namespace std;#define LL unsigned long longconst int maxn=75,r=131;int n,p,m;map<LL,int> mp;int inc(int x,int y){    x+=y;return x>=p?x-p:x;}int dec(int x,int y){    x-=y;return x<0?x+p:x;}int inverse(int x){    int ret=1;    for (int k=p-2;k;k>>=1,x=x*x%p)        if (k&1) ret=ret*x%p;    return ret;}struct mat{    int a[maxn][maxn];    LL h;    void get()    {        h=0;        for (int i=1;i<=n;i++)            for (int j=1;j<=n;j++)                h=h*r+a[i][j];    }    void rd()    {        for (int i=1;i<=n;i++)            for (int j=1;j<=n;j++)                scanf("%d",&a[i][j]);        get();    }    void init()    {        for (int i=1;i<=n;i++)            for (int j=1;j<=n;j++)                a[i][j]=(i==j);        get();    }    mat operator * (const mat &m) const    {        mat ret;        for (int i=1;i<=n;i++)            for (int j=1;j<=n;j++)            {                ret.a[i][j]=0;                for (int k=1;k<=n;k++)                    ret.a[i][j]=inc(ret.a[i][j],a[i][k]*m.a[k][j]%p);            }        ret.get();        return ret;    }    mat inv()    {        mat ret;        int x,t;        ret.init();        for (int i=1;i<=n;i++)        {            x=0;            for (int j=i;j<=n;j++)                if (a[j][i])                {                    x=j;                    break;                }            if (x!=i)                for (int j=1;j<=n;j++)                {                    swap(a[i][j],a[x][j]);                    swap(ret.a[i][j],ret.a[x][j]);                }            t=inverse(a[i][i]);            for (int j=1;j<=n;j++)            {                a[i][j]=a[i][j]*t%p;                ret.a[i][j]=ret.a[i][j]*t%p;            }            for (int j=1;j<=n;j++)                if (j!=i)                {                    t=a[j][i];                    for (int k=1;k<=n;k++)                    {                        a[j][k]=dec(a[j][k],a[i][k]*t%p);                        ret.a[j][k]=dec(ret.a[j][k],ret.a[i][k]*t%p);                    }                }        }        ret.get();        return ret;    }}a,b,c;int main(){    scanf("%d%d",&n,&p);    a.rd();    b.rd();    m=sqrt(p);    c.init();    for (int i=0;i<m;i++)    {        if (!mp.count(c.h)) mp[c.h]=i;        c=c*a;        if (b.h==c.h)        {            printf("%d\n",i+1);            return 0;        }    }    c=c.inv();    for (int i=1;;i++)    {        b=b*c;        if (mp.count(b.h))        {            printf("%d\n",i*m+mp[b.h]);            return 0;        }    }}
  • O(k2logn)递推

bzoj4161 Shlw loves matrixI【2017.5.18】

#include<cstdio>#include<algorithm>using namespace std;#define LL long longconst int maxk=4010,p=1000000007;int n,k,f[maxk],h[maxk];int inc(int x,int y){    x+=y;return x>=p?x-p:x;}int dec(int x,int y){    x-=y;return x<0?x+p:x;}struct mat{    int a[maxk];    mat operator * (const mat &m) const    {        mat ret;        for (int i=0;i<=2*k-2;i++) ret.a[i]=0;        for (int i=0;i<k;i++)            for (int j=0;j<k;j++)                ret.a[i+j]=inc(ret.a[i+j],(LL)a[i]*m.a[j]%p);        for (int i=2*k-2;i>=k;i--)            for (int j=1;j<=k;j++)                ret.a[i-j]=inc(ret.a[i-j],(LL)ret.a[i]*f[j]%p);        return ret;    }}a,b;int main(){    int ans=0;    scanf("%d%d",&n,&k);    for (int i=1;i<=k;i++)    {        scanf("%d",&f[i]);        f[i]=dec(f[i],0);    }    for (int i=0;i<k;i++)    {        scanf("%d",&h[i]);        h[i]=dec(h[i],0);    }    a.a[1]=1;    b.a[0]=1;    for (int i=n-k+1;i;i>>=1,a=a*a)        if (i&1) b=b*a;    for (int i=k;i<=2*k-2;i++)        for (int j=1;j<=k;j++)            h[i]=inc(h[i],(LL)h[i-j]*f[j]%p);    for (int i=0;i<k;i++)        ans=inc(ans,(LL)b.a[i]*h[k+i-1]%p);    printf("%d\n",ans);}

【2017.7.15】

#include<cstdio>#include<algorithm>using namespace std;#define LL long longconst int p=1000000007,maxk=4010;int inc(int x,int y){    x+=y;    return x>=p?x-p:x;}int f[maxk],h[maxk],k,n;struct mat{    int a[maxk];    mat operator * (const mat &m) const    {        mat ret;        for (int i=0;i<=2*k-2;i++)            ret.a[i]=0;        for (int i=0;i<k;i++)            for (int j=0;j<k;j++)                ret.a[i+j]=inc(ret.a[i+j],(LL)a[i]*m.a[j]%p);        for (int i=2*k-2;i>=k;i--)        {            for (int j=1;j<=k;j++) ret.a[i-j]=inc(ret.a[i-j],(LL)ret.a[i]*f[j]%p);            ret.a[i]=0;        }        return ret;    }}base,res;int main(){    //freopen("d.in","r",stdin);    int ans=0;    scanf("%d%d",&n,&k);    for (int i=1;i<=k;i++)    {        scanf("%d",&f[i]);        if (f[i]<0) f[i]+=p;    }    for (int i=0;i<k;i++)    {        scanf("%d",&h[i]);        if (h[i]<0) h[i]+=p;    }    base.a[1]=1;    res.a[0]=1;    for (n-=k-1;n;n>>=1,base=base*base)        if (n&1) res=res*base;    for (int i=k;i<=2*k-2;i++)        for (int j=1;j<=k;j++)            h[i]=inc(h[i],(LL)f[j]*h[i-j]%p);    for (int i=0;i<k;i++) ans=inc(ans,(LL)res.a[i]*h[k+i-1]%p);    printf("%d\n",ans);}
  • 矩阵树定理

【HEOI2015】bzoi4031 小Z的房间【2017.5.18】

#include<cstdio>#include<algorithm>using namespace std;#define LL long longconst int maxn=110,maxl=15,p=1000000000;char map[maxl][maxl];int id[maxl][maxl],a[maxn][maxn],r,c,n;int main(){    int flag=0,x,y,t,ans=1;    scanf("%d%d",&r,&c);    for (int i=1;i<=r;i++)    {        scanf("%s",map[i]+1);        for (int j=1;j<=c;j++)            if (map[i][j]=='.')                id[i][j]=++n;    }    for (int i=1;i<=r;i++)        for (int j=1;j<=c;j++)            if (map[i][j]=='.')            {                x=id[i][j];                if (i<r&&map[i+1][j]=='.')                {                    y=id[i+1][j];                    a[x][y]--;                    a[y][x]--;                    a[x][x]++;                    a[y][y]++;                }                if (j<c&&map[i][j+1]=='.')                {                    y=id[i][j+1];                    a[x][y]--;                    a[y][x]--;                    a[x][x]++;                    a[y][y]++;                }            }    for (int i=1;i<n;i++)        for (int j=1;j<n;j++)            if (a[i][j]<0) a[i][j]+=p;    for (int i=1;i<n;i++)    {        x=0;        for (int j=i;j<n;j++)            if (a[j][i])            {                x=j;                break;            }        if (!x) continue;        if (x!=i)        {            flag^=1;            for (int j=1;j<n;j++) swap(a[i][j],a[x][j]);        }        for (int j=i+1;j<n;j++)            while (a[j][i])            {                if (a[j][i]<a[i][i])                {                    flag^=1;                    for (int k=1;k<n;k++) swap(a[j][k],a[i][k]);                }                t=a[j][i]/a[i][i];                for (int k=1;k<n;k++)                    a[j][k]=(a[j][k]-(LL)a[i][k]*t%p+p)%p;            }    }    for (int i=1;i<n;i++) ans=(LL)ans*a[i][i]%p;    if (flag) ans=(p-ans)%p;    printf("%d\n",ans);}
  • FFT
    bzoj2179 FFT快速傅立叶(FFT)【2017.4.19】
#include<cstdio>#include<cmath>#include<algorithm>using namespace std;const double pi=acos(-1);struct Complex{    double x,y;    Complex operator + (const Complex &c) const    {        return (Complex){x+c.x,y+c.y};    }    Complex operator - (const Complex &c) const    {        return (Complex){x-c.x,y-c.y};    }    Complex operator * (const Complex &c) const    {        return (Complex){x*c.x-y*c.y,x*c.y+y*c.x};    }}a[200010],b[200010],w[200010],t1,t2;char s[200010];int rev[200010],ans[200010],l,m;void fft(Complex *a,int fl){    int x;    for (int i=0;i<l;i++)        if (rev[i]>i) swap(a[i],a[rev[i]]);    for (int i=1;i<=m;i++)        for (int j=0;j<l;j+=1<<i)        {            x=0;            for (int k=j;k<(j+(1<<i-1));k++)            {                t1=a[k];                t2=a[k+(1<<i-1)];                a[k]=t1+t2*w[x];                a[k+(1<<i-1)]=t1-t2*w[x];                x+=fl*(1<<m-i);                if (x<0) x+=l;            }        }}int main(){    int n,nn;    scanf("%d",&n);    scanf("%s",s);    for (int i=0;i<n;i++) a[i].x=s[n-i-1]-'0';    scanf("%s",s);    for (int i=0;i<n;i++) b[i].x=s[n-i-1]-'0';    while ((1<<m)<n*2) m++;    l=1<<m;    w[0]=(Complex){1,0};    w[1]=(Complex){cos(2*pi/l),sin(2*pi/l)};    for (int i=2;i<l;i++)    {        w[i]=w[i/2]*w[i/2];        if (i&1) w[i]=w[i]*w[1];    }    for (int i=0;i<l;i++)        for (int j=0;j<m;j++)            rev[i]|=((i>>j)&1)<<m-j-1;    fft(a,1);    fft(b,1);    for (int i=0;i<l;i++) a[i]=a[i]*b[i];    fft(a,-1);    for (int i=0;i<l;i++) ans[i]=int(a[i].x/l+0.5);    for (int i=0;i<2*n-2;i++)    {        ans[i+1]+=ans[i]/10;        ans[i]%=10;    }    nn=2*n-1;    while (!ans[nn-1]) nn--;    for (int i=nn-1;i>=0;i--) printf("%d",ans[i]);}

【ZJOI2014】bzoj3527 力【2017.5.18】

#include<cstdio>#include<cmath>#include<algorithm>using namespace std;const int maxn=800010;const double pi=acos(-1);struct Complex{    double a,b;    Complex operator + (const Complex &c) const    {        return (Complex){a+c.a,b+c.b};    }    Complex operator - (const Complex &c) const    {        return (Complex){a-c.a,b-c.b};    }    Complex operator * (const Complex &c) const    {        return (Complex){a*c.a-b*c.b,a*c.b+b*c.a};    }}w[maxn],a[maxn],b[maxn],t1,t2;int rev[maxn],n,l,t;void fft(Complex *a,int flag){    int x;    for (int i=0;i<l;i++)        if (rev[i]>i) swap(a[i],a[rev[i]]);    for (int i=1;i<=t;i++)        for (int j=0;j<l;j+=1<<i)        {            x=0;            for (int k=j;k<j+(1<<i-1);k++)            {                t1=a[k];                t2=a[k+(1<<i-1)];                a[k]=t1+t2*w[x];                a[k+(1<<i-1)]=t1-t2*w[x];                x+=flag*(1<<t-i);                if (x<0) x+=l;            }        }}int main(){    scanf("%d",&n);    for (int i=0;i<n;i++) scanf("%lf",&a[i].a);    for (int i=0;i<n-1;i++) b[i].a=-1/((double)(n-i-1)*(n-i-1));    for (int i=n;i<2*n-1;i++) b[i].a=1/((double)(i-n+1)*(i-n+1));    l=1,t=0;    while (l<4*n-3) l<<=1,t++;    for (int i=0;i<l;i++) w[i]=(Complex){cos(2*pi*i/l),sin(2*pi*i/l)};    for (int i=0;i<l;i++)        for (int j=0;j<t;j++) rev[i]|=((i>>j)&1)<<(t-j-1);    fft(a,1);    fft(b,1);    for (int i=0;i<l;i++) a[i]=a[i]*b[i];    fft(a,-1);    for (int i=n-1;i<2*n-1;i++) printf("%.3f\n",a[i].a/l);}
  • 辛普森自适应积分

计算几何

  • 射线法
  • 凸包
  • 旋转卡壳
  • 半平面交

图论

  • 树链剖分
  • LCT
    【HNOI2010】bzoj2002 弹飞绵羊
#include<cstdio>#include<algorithm>using namespace std;const int maxn=400010;int rd(){    int x=0;    char c=getchar();    while (c<'0'||c>'9') c=getchar();    while (c>='0'&&c<='9')    {        x=x*10+c-'0';        c=getchar();    }    return x;}int fa[maxn],son[maxn][2],siz[maxn],a[maxn],inv[maxn],sta[maxn],n;void down(int x){    if (inv[x])    {        inv[x]=0;        swap(son[x][0],son[x][1]);        if (son[x][0]) inv[son[x][0]]^=1;        if (son[x][1]) inv[son[x][1]]^=1;    }}void up(int x){    down(x);    siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;}int isroot(int x){    return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}void rot(int u,int f){    int v=son[u][f],x=son[v][f^1],y=fa[u];    if (son[y][0]==u) son[y][0]=v;    if (son[y][1]==u) son[y][1]=v;    fa[v]=y;    son[v][f^1]=u;    fa[u]=v;    son[u][f]=x;    if (x) fa[x]=u;    up(u);    up(v);}void splay(int u){    int top=0,x,y,fx,fy;    for (int i=u;;i=fa[i])    {        sta[++top]=i;        if (isroot(i)) break;    }    for (;top;top--) down(sta[top]);    while (!isroot(u))    {        x=fa[u];        fx=son[x][1]==u;        if (isroot(x)) rot(x,fx);        else        {            y=fa[x];            fy=son[y][1]==x;            if (fx==fy) rot(y,fy),rot(x,fx);            else rot(x,fx),rot(y,fy);        }    }}void access(int u){    int v=0;    while (u)    {        splay(u);        son[u][1]=v;        up(u);        v=u;        u=fa[u];    }}void makeroot(int x){    access(x);    splay(x);    inv[x]^=1;    up(x);}void link(int x,int y){    makeroot(y);    fa[x]=y;}void cut(int x,int y){    makeroot(y);    access(x);    splay(x);    son[x][0]=fa[y]=0;    up(x);}int qry(int x){    makeroot(n+1);    access(x);    splay(x);    return siz[x]-1;}int main(){    int q,opt,x,y;    n=rd();    for (int i=1;i<=n;i++) siz[i]=1;    for (int i=1;i<=n;i++)    {        a[i]=rd();        if (i+a[i]>n) a[i]=n-i+1;        link(i,i+a[i]);    }    q=rd();    while (q--)    {        opt=rd();        if (opt==1) printf("%d\n",qry(rd()+1));        else        {            x=rd()+1;            y=rd();            cut(x,x+a[x]);            a[x]=y;            if (x+a[x]>n) a[x]=n-x+1;            link(x,x+a[x]);        }    }}

bzoj2631 tree【2017.5.16】

#include<cstdio>#include<algorithm>using namespace std;#define UI unsigned intconst int maxn=200010,p=51061;int rd(){    int x=0;    char c=getchar();    while (c<'0'||c>'9') c=getchar();    while (c>='0'&&c<='9')    {        x=x*10+c-'0';        c=getchar();    }    return x;}char rdc(){    char c=getchar();    while (c!='+'&&c!='*'&&c!='/'&&c!='-') c=getchar();    return c;}int inc(int x,int y){    x+=y;return x>=p?x-p:x;}int son[maxn][2],fa[maxn],tagp[maxn],tagm[maxn],sum[maxn],val[maxn],siz[maxn],inv[maxn],sta[maxn],n;int is(int u){    return son[fa[u]][0]!=u&&son[fa[u]][1]!=u;}void down(int u){    int v;    if (inv[u])    {        inv[u]=0;        swap(son[u][0],son[u][1]);        if (v=son[u][0]) inv[v]^=1;        if (v=son[u][1]) inv[v]^=1;     }    if (tagm[u]!=1)    {        val[u]=(UI)val[u]*tagm[u]%p;        sum[u]=(UI)sum[u]*tagm[u]%p;        if (v=son[u][0])        {            tagm[v]=(UI)tagm[v]*tagm[u]%p;            tagp[v]=(UI)tagp[v]*tagm[u]%p;        }        if (v=son[u][1])        {            tagm[v]=(UI)tagm[v]*tagm[u]%p;            tagp[v]=(UI)tagp[v]*tagm[u]%p;        }        tagm[u]=1;    }    if (tagp[u])    {        val[u]=inc(val[u],tagp[u]);        sum[u]=inc(sum[u],(UI)tagp[u]*siz[u]%p);        if (v=son[u][0]) tagp[v]=inc(tagp[v],tagp[u]);        if (v=son[u][1]) tagp[v]=inc(tagp[v],tagp[u]);        tagp[u]=0;    }}void up(int u){    down(u);    if (son[u][0]) down(son[u][0]);    if (son[u][1]) down(son[u][1]);    int v;    sum[u]=val[u];    siz[u]=1;    if (v=son[u][0])    {        sum[u]=inc(sum[u],sum[v]);        siz[u]=siz[u]+siz[v];    }    if (v=son[u][1])    {        sum[u]=inc(sum[u],sum[v]);        siz[u]=siz[u]+siz[v];    }}void rot(int u,int f){    int v=son[u][f],x=son[v][f^1],y=fa[u];    if (!is(u)) son[y][son[y][1]==u]=v;    fa[v]=y;    son[v][f^1]=u;    fa[u]=v;    son[u][f]=x;    if (x) fa[x]=u;    up(u);    up(v);}void splay(int u){    int v,x,y,xx,yy,t=u,top=0;    while (1)    {        sta[++top]=t;        if (is(t)) break;        t=fa[t];    }    for (;top;top--) down(sta[top]);    while (!is(u))    {        x=fa[u];        xx=son[x][1]==u;        if (is(x)) rot(x,xx);        else        {            y=fa[x];            yy=son[y][1]==x;            if (xx==yy) rot(y,yy),rot(x,xx);            else rot(x,xx),rot(y,yy);        }    }}void access(int u){    int v=0,t=u;    while (u)    {        splay(u);        son[u][1]=v;        up(u);        v=u;        u=fa[u];    }    splay(t);}void make(int u){    access(u);    inv[u]^=1;    up(u);}void link(int u,int v){    make(u);    fa[u]=v;}void cut(int u,int v){    make(u);    access(v);    son[v][0]=fa[u]=0;    up(v);}int query(int u,int v){    make(u);    access(v);    return sum[v];}void modip(int u,int v,int x){    make(u);    access(v);    tagp[v]=inc(tagp[v],x);}void modim(int u,int v,int x){    make(u);    access(v);    tagp[v]=(UI)tagp[v]*x%p;    tagm[v]=(UI)tagm[v]*x%p;}int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    char c;    int u,v,x,y,q;    n=rd();    q=rd();    for (int i=1;i<=n;i++) sum[i]=val[i]=tagm[i]=siz[i]=1;    for (int i=1;i<n;i++)    {        u=rd();        v=rd();        link(u,v);    }    while (q--)    {        c=rdc();        u=rd();        v=rd();        if (c=='/') printf("%d\n",query(u,v));        else        {            x=rd();            if (c=='+') modip(u,v,x);            else if (c=='*') modim(u,v,x);            else            {                y=rd();                cut(u,v);                link(x,y);            }        }    }}
  • 点分治
    poj1741 Tree【2017.5.16】
#include<cstdio>#include<algorithm>using namespace std;const int maxn=10010;struct node{    int bel,dis;    bool operator < (const node &n) const    {        return dis<n.dis;    }}a[maxn];int fir[maxn],vis[maxn],ne[2*maxn],to[2*maxn],w[2*maxn],size[maxn],val[maxn],sum[maxn],rt,n,m,ans,S,tot;void add(int num,int u,int v,int x){    ne[num]=fir[u];    fir[u]=num;    to[num]=v;    w[num]=x;}void dfs1(int u,int fa){    size[u]=1;    val[u]=0;    for (int i=fir[u];i;i=ne[i])        if (to[i]!=fa&&!vis[to[i]])        {            dfs1(to[i],u);            size[u]+=size[to[i]];            val[u]=max(val[u],size[to[i]]);        }    val[u]=max(val[u],S-size[u]);    if (rt==-1||val[u]<val[rt]) rt=u;}void dfs2(int u,int fa,int b,int d){    size[u]=1;    a[++tot]=(node){b,d};    for (int i=fir[u];i;i=ne[i])        if (to[i]!=fa&&!vis[to[i]])        {            dfs2(to[i],u,b,d+w[i]);            size[u]+=size[to[i]];        }}void solve(int u){    int r,num=0,s=0;    rt=-1;    dfs1(u,-1);    r=rt;    a[tot=1]=(node){0,0};    for (int i=fir[r];i;i=ne[i])        if (!vis[to[i]])            dfs2(to[i],r,++num,w[i]);    sort(a+1,a+tot+1);    for (int i=0;i<=num;i++) sum[i]=0;    for (int i=tot,j=0;i;i--)    {        while (j<tot&&a[j+1].dis+a[i].dis<=m) sum[a[++j].bel]++;        ans+=j-sum[a[i].bel];    }    vis[r]=1;    for (int i=fir[r];i;i=ne[i])        if (!vis[to[i]])        {            S=size[to[i]];            solve(to[i]);        }}void solve(){    int u,v,x;    for (int i=1;i<=n;i++) fir[i]=vis[i]=0;    ans=0;    for (int i=1;i<n;i++)    {        scanf("%d%d%d",&u,&v,&x);        add(i*2,u,v,x);        add(i*2+1,v,u,x);    }    S=n;    solve(1);    printf("%d\n",ans/2);}int main(){    while (scanf("%d%d",&n,&m)&&n) solve();}
  • 边分治
  • 动态点分治

【ZJOI2007】bzoj1095 捉迷藏【2017.5.18】

#include<cstdio>#include<queue>#include<algorithm>using namespace std;const int maxn=100010;struct heap{    priority_queue<int> a,b;    void ins(int x)    {        a.push(x);    }    void del(int x)    {        b.push(x);    }    int size()    {        return a.size()-b.size();    }    int top()    {        while (!b.empty()&&a.top()==b.top())        {            a.pop();            b.pop();        }        return a.top();    }    int get()    {        int x=top();        del(x);        int y=top();        ins(x);        return x+y;    }}q1[maxn],q2[maxn],q3;int fir[maxn],ne[2*maxn],to[2*maxn],vis[maxn],size[maxn],val[maxn],fa[maxn],flag[maxn],mn[2*maxn][20],pos[maxn],dep[maxn],log[2*maxn],n,rt,clo;void add(int num,int u,int v){    ne[num]=fir[u];    fir[u]=num;    to[num]=v;}void dfs0(int u,int fa,int d){    dep[u]=d;    mn[pos[u]=++clo][0]=d;    for (int i=fir[u];i;i=ne[i])        if (to[i]!=fa)        {            dfs0(to[i],u,d+1);            mn[++clo][0]=d;        }}void dfs1(int u,int fa){    size[u]=1;    for (int i=fir[u];i;i=ne[i])        if (!vis[to[i]]&&to[i]!=fa)        {            dfs1(to[i],u);            size[u]+=size[to[i]];        }}int dfs2(int u,int fa,int S){    int ret=-1,x;    val[u]=S-size[u];    for (int i=fir[u];i;i=ne[i])        if (!vis[to[i]]&&to[i]!=fa)        {            x=dfs2(to[i],u,S);            val[u]=max(val[u],size[to[i]]);            if (ret==-1||val[x]<val[ret]) ret=x;        }    if (ret==-1||val[u]<val[ret]) ret=u;    return ret;}void dfs3(int u,int fa,int bel,int dis){    q1[bel].ins(dis);    for (int i=fir[u];i;i=ne[i])        if (!vis[to[i]]&&to[i]!=fa)            dfs3(to[i],u,bel,dis+1);}int solve(int u){    dfs1(u,-1);    int r=dfs2(u,-1,size[u]),x;    vis[r]=1;    for (int i=fir[r];i;i=ne[i])        if (!vis[to[i]])        {            x=solve(to[i]);            dfs3(to[i],r,x,1);            fa[x]=r;            q2[r].ins(q1[x].top());        }    q2[r].ins(0);    vis[r]=0;    if (q2[r].size()>=2) q3.ins(q2[r].get());    return r;}int dis(int u,int v){    int x=pos[u],y=pos[v],k;    if (x>y) swap(x,y);    k=log[y-x+1];    return dep[u]+dep[v]-2*min(mn[x][k],mn[y-(1<<k)+1][k]);}void ins(int u){    if (q2[u].size()>=2) q3.del(q2[u].get());    q2[u].ins(0);    if (q2[u].size()>=2) q3.ins(q2[u].get());    for (int i=u;fa[i];i=fa[i])    {        if (q2[fa[i]].size()>=2) q3.del(q2[fa[i]].get());        if (q1[i].size()) q2[fa[i]].del(q1[i].top());        q1[i].ins(dis(u,fa[i]));        if (q1[i].size()) q2[fa[i]].ins(q1[i].top());        if (q2[fa[i]].size()>=2) q3.ins(q2[fa[i]].get());    }}void del(int u){    if (q2[u].size()>=2) q3.del(q2[u].get());    q2[u].del(0);    if (q2[u].size()>=2) q3.ins(q2[u].get());    for (int i=u;fa[i];i=fa[i])    {        if (q2[fa[i]].size()>=2) q3.del(q2[fa[i]].get());        if (q1[i].size()) q2[fa[i]].del(q1[i].top());        q1[i].del(dis(u,fa[i]));        //printf("%d\n",q1[i].size());        if (q1[i].size()) q2[fa[i]].ins(q1[i].top());        if (q2[fa[i]].size()>=2) q3.ins(q2[fa[i]].get());    }}int main(){    int u,v,q,now;    char c[3];    scanf("%d",&n);    for (int i=1;i<n;i++)    {        scanf("%d%d",&u,&v);        add(i*2,u,v);        add(i*2+1,v,u);    }    dfs0(1,-1,1);    for (int i=1;(1<<i)<=clo;i++) log[1<<i]=i;    for (int i=3;i<=clo;i++)        if (!log[i]) log[i]=log[i-1];    for (int k=1;k<=log[clo];k++)        for (int i=1;i+(1<<k)-1<=clo;i++)            mn[i][k]=min(mn[i][k-1],mn[i+(1<<k-1)][k-1]);    rt=solve(1);    now=n;    scanf("%d",&q);    while (q--)    {        scanf("%s",c);        if (c[0]=='C')        {            scanf("%d",&u);            if (flag[u]) ins(u),now++;            else del(u),now--;            flag[u]^=1;        }        else        {            if (now==0) printf("-1\n");            else if (now==1) printf("0\n");            else printf("%d\n",q3.top());        }    }}
  • 2-SAT

poj3678 Katu Puzzle【2017.5.19】

#include<cstdio>#include<algorithm>using namespace std;const int maxn=2010,maxm=2000010;int fir[maxn],ne[maxm],to[maxm],dfn[maxn],low[maxn],sta[maxn],bel[maxn],in[maxn],n,m,num,clo,tot,top;void add(int u,int v){    num++;    ne[num]=fir[u];    fir[u]=num;    to[num]=v;}void dfs(int u){    int x;    dfn[u]=low[u]=++clo;    sta[++top]=u;    in[u]=1;    for (int i=fir[u];i;i=ne[i])        if (!dfn[to[i]])        {            dfs(to[i]);            low[u]=min(low[u],low[to[i]]);        }        else if (in[to[i]]) low[u]=min(low[u],dfn[to[i]]);    if (low[u]==dfn[u])    {        tot++;        do        {            x=sta[top--];            bel[x]=tot;            in[x]=0;        }        while (x!=u);    }}int main(){    int u,v,x;    char s[10];    scanf("%d%d",&n,&m);    while (m--)    {        scanf("%d%d%d%s",&u,&v,&x,s);        switch (s[0])        {            case 'A':                if (x==0)                {                    add(v*2+1,u*2);                    add(u*2+1,v*2);                }                else                {                    add(u*2,u*2+1);                    add(v*2,v*2+1);                }                break;            case 'O':                if (x==0)                {                    add(u*2+1,u*2);                    add(v*2+1,v*2);                }                else                {                    add(u*2,v*2+1);                    add(v*2,u*2+1);                }                break;            case 'X':                if (x==0)                {                    add(u*2,v*2);                    add(v*2,u*2);                    add(u*2+1,v*2+1);                    add(v*2+1,u*2+1);                }                else                {                    add(u*2,v*2+1);                    add(v*2,u*2+1);                    add(u*2+1,v*2);                    add(v*2+1,u*2);                }                break;        }    }    for (int i=0;i<n*2;i++)        if (!dfn[i]) dfs(i);    for (int i=0;i<n;i++)        if (bel[i*2]==bel[i*2+1])        {            printf("NO\n");            return 0;        }    printf("YES\n");}

动态规划

  • 斜率优化dp
    【APIO2010】bzoj1911 特别行动队
#include<cstdio>#include<algorithm>using namespace std;#define LL long longconst int maxn=1000010;int rd(){    int x=0,f=1;    char c=getchar();    while (c<'0'||c>'9')    {        if (c=='-') f=-1;        c=getchar();    }    while (c>='0'&&c<='9')    {        x=x*10+c-'0';        c=getchar();    }    return x*f;}LL dp[maxn],s[maxn],h[maxn],g[maxn],a,b,c;int que[maxn],n;double get(int i,int j){    return (double)(h[j]-h[i])/(s[j]-s[i]);}int main(){    int hd=1,tl=1;    n=rd();    a=rd();    b=rd();    c=rd();    for (int i=1;i<=n;i++) s[i]=s[i-1]+rd();    for (int i=1;i<=n;i++)    {        while (hd<tl&&get(que[hd],que[hd+1])<=-2*a*s[i]) hd++;        dp[i]=dp[que[hd]]+a*(s[i]-s[que[hd]])*(s[i]-s[que[hd]])+b*(s[i]-s[que[hd]])+c;        h[i]=-a*s[i]*s[i]+b*s[i]-dp[i];        while (hd<tl&&get(que[tl-1],que[tl])>=get(que[tl],i)) tl--;        que[++tl]=i;    }    printf("%lld\n",dp[n]);}
  • 插头dp

【SCOI2011】bzoj2331 地板【2017.5.19】

#include<cstdio>#include<algorithm>using namespace std;const int p=20110520;char mp[110][110];int dp[2][4200010],last[4200010],f[2][4200010],r,c,clo,tot,y;int inc(int x,int y){    x+=y;return x>=p?x-p:x;}void upd(int x){    if (last[x]==clo+1) dp[clo&1^1][x]=inc(dp[clo&1^1][x],y);    else    {        last[x]=clo+1;        f[clo&1^1][++tot]=x;        dp[clo&1^1][x]=y;    }}int main(){    int x,t1,ans=0;    scanf("%d%d",&r,&c);    for (int i=1;i<=r;i++) scanf("%s",mp[i]+1);    if (r<c)    {        for (int i=1;i<=c;i++)            for (int j=i+1;j<=c;j++)                swap(mp[i][j],mp[j][i]);        swap(r,c);    }    f[1][tot=1]=0;    dp[1][0]=1;    for (int i=1;i<=r;i++)        for (int j=1;j<=c;j++)        {            clo++;            t1=tot;            tot=0;            for (int k=1;k<=t1;k++)            {                x=f[clo&1][k];                y=dp[clo&1][x];                if (mp[i][j]=='*')                {                    if (!(x&1)&&!((x>>2)&1)) upd(x>>2);                    continue;                }                if (!(x&1))                {                    if (!(x&4))                    {                        upd((x>>2)|(1<<2*c));                        if (j<c)                        {                            upd((x>>2)|1);                            upd((x>>2)|3|(3<<2*c));                        }                    }                    else if (!(x&8))                    {                        upd(((x>>2)^1)|(1<<2*c));                        if (j<c) upd((x>>2)|3);                    }                    else                    {                        upd((x>>2)^3);                        upd(((x>>2)^3)|(3<<2*c));                    }                }                else if (!(x&2))                {                    if (!(x&4))                    {                        if (j<c) upd((x>>2)|1);                        upd((x>>2)|(3<<2*c));                    }                    else if (!(x&8)) upd((x>>2)^1);                }                else                {                    if (!(x&4))                    {                        upd(x>>2);                        if (j<c) upd((x>>2)|3);                    }                }            }        }    printf("%d\n",last[0]==clo+1?dp[clo&1^1][0]:0);}
  • 数位dp
  • 四边形不等式

其他算法

  • CDQ分治
    bzoj3262 陌上花开【2017.5.16】
#include<cstdio>#include<algorithm>using namespace std;const int maxn=100010,maxm=200010;int rd(){    int x=0;    char c=getchar();    while (c<'0'||c>'9') c=getchar();    while (c>='0'&&c<='9')    {        x=x*10+c-'0';        c=getchar();    }    return x;}struct flower{    int a,b,c,res,num;    bool operator < (const flower &f) const    {        if (a!=f.a) return a<f.a;        if (b!=f.b) return b<f.b;        return c<f.c;    }}a[maxn],b[maxn];int s[maxm],ans[maxn],n,m;void add(int k,int x){    for (;k<=m;k+=k&-k) s[k]+=x;}int qry(int k){    int ret=0;    for (;k;k-=k&-k) ret+=s[k];    return ret;}void solve(int l,int r){    if (l==r) return;    int mid=(l+r)/2;    solve(l,mid);    solve(mid+1,r);    for (int i=l;i<=r;i++) b[i]=a[i];    for (int i=l,j=mid+1,now=l;i<=mid||j<=r;)        if (j>r||(i<=mid&&b[i].b<=b[j].b))        {            add(b[i].c,b[i].num);            a[now++]=b[i++];        }        else        {            b[j].res+=qry(b[j].c);            a[now++]=b[j++];        }    for (int i=l;i<=mid;i++) add(b[i].c,-b[i].num);}int main(){    int N=1;    n=rd();    m=rd();    for (int i=1;i<=n;i++)    {        a[i].a=rd();        a[i].b=rd();        a[i].c=rd();        a[i].num=1;    }    sort(a+1,a+n+1);    b[1]=a[1];    for (int i=2;i<=n;i++)        if (a[i-1]<a[i]) b[++N]=a[i];        else b[N].num++;    for (int i=1;i<=N;i++) a[i]=b[i];    solve(1,N);    for (int i=1;i<=N;i++) ans[a[i].res+a[i].num-1]+=a[i].num;    for (int i=0;i<n;i++) printf("%d\n",ans[i]);}
  • 整体二分

bzoj2738 矩阵乘法【2017.5.16】

#include<cstdio>#include<algorithm>using namespace std;const int maxn=510,maxq=60010;int rd(){    int x=0;    char c=getchar();    while (c<'0'||c>'9') c=getchar();    while (c>='0'&&c<='9')    {        x=x*10+c-'0';        c=getchar();    }    return x;}struct qry{    int x1,y1,x2,y2,id,res,k;}f[maxq],g[maxq];struct node{    int x,y,v;    bool operator < (const node &n) const    {        return v<n.v;    }}a[maxn*maxn];int s[maxn][maxn],ans[maxq],n,q,tot;void add(node a){    for (int i=a.x;i<=n;i+=i&-i)        for (int j=a.y;j<=n;j+=j&-j)            s[i][j]++;}void dec(node a){    for (int i=a.x;i<=n;i+=i&-i)        for (int j=a.y;j<=n;j+=j&-j)            s[i][j]--;}int query(qry a){    int ret=0;    for (int i=a.x2;i;i-=i&-i)        for (int j=a.y2;j;j-=j&-j)            ret+=s[i][j];    for (int i=a.x1-1;i;i-=i&-i)        for (int j=a.y2;j;j-=j&-j)            ret-=s[i][j];    for (int i=a.x2;i;i-=i&-i)        for (int j=a.y1-1;j;j-=j&-j)            ret-=s[i][j];    for (int i=a.x1-1;i;i-=i&-i)        for (int j=a.y1-1;j;j-=j&-j)            ret+=s[i][j];    return ret;}void solve(int l,int r,int L,int R){    if (L==R)    {        for (int i=l;i<=r;i++) f[i].res=a[L].v;        return;    }    int mid=(L+R)/2,m=r,x;    for (int i=L;i<=mid;i++) add(a[i]);    for (int i=l,j=l,k=r;i<=r;i++)    {        x=query(f[i]);        if (f[i].k<=x) g[j++]=f[i];        else        {            f[i].k-=x;            g[k--]=f[i];            m=k;        }    }    for (int i=L;i<=mid;i++) dec(a[i]);    for (int i=l;i<=r;i++) f[i]=g[i];    solve(l,m,L,mid);    solve(m+1,r,mid+1,R);}int main(){    int x1,y1,x2,y2,k;    n=rd();    q=rd();    for (int i=1;i<=n;i++)        for (int j=1;j<=n;j++)            a[++tot]=(node){i,j,rd()};    for (int i=1;i<=q;i++)    {        x1=rd();        y1=rd();        x2=rd();        y2=rd();        k=rd();        f[i]=(qry){x1,y1,x2,y2,i,0,k};    }    sort(a+1,a+tot+1);    solve(1,q,1,tot);    for (int i=1;i<=q;i++) ans[f[i].id]=f[i].res;    for (int i=1;i<=q;i++) printf("%d\n",ans[i]);}

【ZJOI2013】bzoj3110 K大数查询【2017.7.14】

#include<cstdio>#include<algorithm>using namespace std;#define UI unsigned intconst int maxn=50010,maxt=2000000;int rdi(){    int x=0,f=1;    char c=getchar();    while (c<'0'||c>'9')    {        if (c=='-') f=-1;        c=getchar();    }    while (c>='0'&&c<='9')    {        x=x*10+c-'0';        c=getchar();    }    return x*f;}UI rdu(){    UI x=0;    char c=getchar();    while (c<'0'||c>'9') c=getchar();    while (c>='0'&&c<='9')    {        x=x*10+c-'0';        c=getchar();    }    return x;}struct str{    int l,r,id,f;    UI x;}a[maxn],b[maxn],c[maxn];UI sum[maxt];int n,m,o,val[maxn],ord[maxn],ans[maxn],tag[maxt];void down(int u,int L,int R){    if (L<R)    {        tag[u*2]+=tag[u];        tag[u*2+1]+=tag[u];    }    sum[u]+=(UI)tag[u]*(R-L+1);    tag[u]=0;}UI qry(int u,int L,int R,int l,int r){    down(u,L,R);    if (l<=L&&R<=r) return sum[u];    int mid=(L+R)/2;    UI ret=0;    if (l<=mid) ret=qry(u*2,L,mid,l,r);    if (r>mid) ret+=qry(u*2+1,mid+1,R,l,r);    return ret;}void modi(int u,int L,int R,int l,int r,int x){    if (l<=L&&R<=r)    {        tag[u]+=x;        return;    }    down(u,L,R);    int mid=(L+R)/2;    if (l<=mid) modi(u*2,L,mid,l,r,x);    if (r>mid) modi(u*2+1,mid+1,R,l,r,x);    down(u*2,L,mid);    down(u*2+1,mid+1,R);    sum[u]=sum[u*2]+sum[u*2+1];}void solve(int L,int R,int l,int r){    if (l==r)    {        for (int i=L;i<=R;i++)            if (a[i].f==2) ans[a[i].id]=l;        return;    }    int mid=(l+r)/2,n1=0,n2=0;    UI x;    for (int i=L;i<=R;i++)        if (a[i].f==1)        {            if ((int)a[i].x>mid)            {                modi(1,1,n,a[i].l,a[i].r,1);                c[++n2]=a[i];            }            else b[++n1]=a[i];        }        else        {            x=qry(1,1,n,a[i].l,a[i].r);            if (x>=a[i].x) c[++n2]=a[i];            else            {                a[i].x-=x;                b[++n1]=a[i];            }        }    for (int i=L;i<=R;i++)        if (a[i].f==1&&(int)a[i].x>mid)            modi(1,1,n,a[i].l,a[i].r,-1);    for (int i=1;i<=n1;i++) a[L+i-1]=b[i];    for (int i=1;i<=n2;i++) a[L+n1+i-1]=c[i];    solve(L,L+n1-1,l,mid);    solve(L+n1,R,mid+1,r);}int main(){    //freopen("b.in","r",stdin);    //freopen("b.out","w",stdout);    n=rdi();    m=rdi();    for (int i=1;i<=m;i++)    {        a[i].f=rdi();        a[i].l=rdi();        a[i].r=rdi();        if (a[i].f==1) val[i]=ord[++o]=rdi();        else a[i].x=rdu();        a[i].id=i;    }    sort(ord+1,ord+o+1);    o=unique(ord+1,ord+o+1)-ord-1;    for (int i=1;i<=m;i++)        if (a[i].f==1) a[i].x=lower_bound(ord+1,ord+o+1,val[i])-ord;    solve(1,m,1,o);    for (int i=1;i<=m;i++)        if (ans[i]) printf("%d\n",ord[ans[i]]);}
1 0