• noip2017酱油记前篇


    noip day0

    马上就要打酱油了>_<,真是害怕。昨天就整理了一下noip要写的模板

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define ll long long
    using namespace std;
    const int maxn=100000+233;
    inline int read(){
        int an=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=an*10+ch-'0';ch=getchar();}
        return an*f;
    }
    struct saber{
    int an,l,r;
    }t[maxn<<2];
    int tt[maxn],a[maxn],b[maxn],dp[maxn],ans,n;
    inline void build(int k,int l,int r){
        t[k].l=l;t[k].r=r;
        if(l==r)return ;
        int mid=l+r>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
    }
    inline int ask(int k,int x,int y){
        int l=t[k].l,r=t[k].r;
        if(l==x&&r==y)return t[k].an;
        int mid=l+r>>1;
        if(mid>=y)return ask(k<<1,x,y);
        else if(x>mid)return ask(k<<1|1,x,y);
        else return max(ask(k<<1,x,mid),ask(k<<1|1,mid+1,y));
    }
    inline void add(int k,int wi,int fin){
        int l=t[k].l,r=t[k].r;
        if(l==fin&&r==fin){t[k].an=wi;return;}
        int mid=l+r>>1;
        if(mid>=fin)add(k<<1,wi,fin);
        else add(k<<1|1,wi,fin);
        t[k].an=max(t[k<<1].an,t[k<<1|1].an);
    }
    int main(){
        n=read();
        for(int i=1;i<=n;i++)a[i]=read();
        for(int i=1;i<=n;i++)b[i]=read();
        for(int i=1;i<=n;i++)tt[b[i]]=i;
        for(int i=1;i<=n;i++)a[i]=tt[a[i]];
        build(1,1,n);
        for(int i=1;i<=n;i++){
            int x=ask(1,1,a[i]);
            dp[i]=x+1;
            add(1,dp[i],a[i]);
            ans=max(ans,dp[i]);
        }
        cout<<ans;
    }
    【模板】最长公共子序列

    类似导弹拦截


    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #define _x .first
    #define _y .second
    using namespace std;
    const int maxn=10000+2333;
    inline int read(){
        int an=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){ch=getchar();}
        while('0'<=ch&&ch<='9'){an=(an<<3)+(an<<1)+(ch^48);ch=getchar();}
        return an;
    }
    int tmp;
    struct saber{
    int l,r,t,id;
    }q[maxn];
    vector< pair<int,int > > change;
    
    int n,m,a[maxn],block,link[maxn],cntq,cnt,ans[maxn];
    int color[maxn*10],size;
    char c;
    bool operator <(saber x,saber y){return (link[x.l]<link[y.l])||(link[x.l]==link[y.l]&&x.r<y.r)||(link[x.l]==link[y.l]&&x.r==y.r&&x.t<y.t);}
    
    inline void Change(int x,int i){
        if(change[x] _x>=q[i].l&&change[x] _x<=q[i].r){
            color[a[change[x] _x]]--;
            if(color[a[change[x] _x]]==0)tmp--;
            if(color[change[x] _y]==0)tmp++;
            color[change[x] _y]++;
        }
        swap(a[change[x] _x],change[x] _y);
    }
    int main(){
    //    ios::sync_with_stdio(0);
        cin>>n>>m;
        size=sqrt(n);
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=m;i++){
            link[i]=block+1;
            if(!(i%size))block++;
        }
        change.push_back(make_pair(0,0));
        for(int i=1;i<=m;i++){
            cin>>c;
            if(c=='R'){
                ++cntq;
                int x,y;cin>>x>>y;
                change.push_back( make_pair(x,y) );
            }
            else{
                int x,y;cin>>x>>y;
                q[++cnt]=(saber){x,y,cntq,cnt};
            }
        }
        sort(q+1,q+1+cnt);
        int L=0,R=0,now=0;
        for(int i=1;i<=cnt;i++){
            while(L<q[i].l){color[a[L]]--;if(!color[a[L]])tmp--;L++;}
            while(L>q[i].l){L--;color[a[L]]++;if(color[a[L]]==1)tmp++;}
            while(R<q[i].r){R++;color[a[R]]++;if(color[a[R]]==1)tmp++;}
            while(R>q[i].r){color[a[R]]--;if(color[a[R]]==0)tmp--;R--;}
            while(now<q[i].t){now++,Change(now,i);}
            while(now>q[i].t){Change(now,i);now--;}
            ans[q[i].id]=tmp;
        }
        for(int i=1;i<=cnt;i++)cout<<ans[i]<<"
    ";
        return 0;
    }
    【模板】分块/带修改莫队(数颜色)

    分块处理<优雅的暴力>


    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define ll long long
    const int mod=1e9+7;
    using namespace std;
    int n,T;
    inline int read(){
        int an=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=an*10+ch-'0';ch=getchar();}
        return an*f;
    }
    struct saber{
    ll a[5][5];
    }b,a;
    saber operator *(saber A,saber B){
        saber re;
        memset(re.a,0,sizeof re.a);
        for(int k=1;k<=3;k++)
        for(int i=1;i<=3;i++)
        for(int j=1;j<=3;j++)
        re.a[i][j]=(re.a[i][j]+A.a[i][k]*B.a[k][j])%mod;
        return re;
    }
    inline saber work(saber x,int y){
        saber re;
        re=x;
        while(y){
            if(y&1)re=re*x;
            x=x*x;
            y>>=1;
        }
        return re;
    }
    int main(){
        b.a[1][3]=1;b.a[2][1]=1;
        b.a[3][3]=1;b.a[3][2]=1;
        a.a[1][1]=1;a.a[1][2]=1;a.a[1][3]=1;
        T=read();
        while(T){
            T--;
            n=read();
            if(n<=3){cout<<"1
    ";continue;}
            saber k=work(b,n-4);
            k=a*k;
            cout<<k.a[1][3]<<"
    ";
        }
    }
    P1939 【模板】矩阵加速(数列)

    推出矩阵乱搞就好了


    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    int read(){
        int an=0,f=1;
        char ch=getchar();
        while(!('0'<=ch&&ch<='9')){if(ch=='-')f=-f;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=an*10+ch-'0';ch=getchar();}
        return an*f;
    }
    const int maxn=5099;
    const int maxm=200999;
    int fa[maxn],cnt,so[maxm];
    long long ans;
    int m,n,tot;
    struct saber{
    int from,to,wi;
    }b[maxm];
    void add(int x,int y,int z){
        cnt++;
        b[cnt].from=x;
        b[cnt].to=y;
        b[cnt].wi=z;
    }
    bool pai(int x,int y){
        return b[x].wi<b[y].wi;
    }
    int found(int x){
        if(fa[x]!=x)fa[x]=found(fa[x]);
        return fa[x];
    }
    int main(){
        n=read();m=read();
        for(int i=1;i<=m;i++){
            int x,y,z;
            x=read();y=read();z=read();
            add(x,y,z);
        }
        for(int i=1;i<=n;i++)fa[i]=i;
        for(int i=1;i<=m;i++)so[i]=i;
        sort(so+1,so+m+1,pai);
        for(int i=1;i<=m;i++){
            int x=b[so[i]].from;
            int y=b[so[i]].to;
            int f1=found(x);int f2=found(y);
            if(f1!=f2){ans+=b[so[i]].wi;fa[f1]=f2;}
        }
        cout<<ans;
        return 0;
    }
    【模板】最小生成树

    记得路径压缩


    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    #define IN 599962
    int a[IN],c[IN];
    int m,n;
    int LO(int i){return (-i)&i;}
    int  ans(int k){
         int ans=0;
         for(int i=k;i>0;i-=LO(i))ans+=c[i];
         return ans;
    }
    void F(int k){
        printf("%d",ans(k));
    }
    void F(int k1,int k2,int k3){
         for(int i=k1;i<=n;i+=LO(i))c[i]+=k3;
         for(int i=k2+1;i<=n;i+=LO(i))c[i]-=k3;
         }
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++){
          scanf("%d",&a[i]);
          for(int j=i;j<=n;j+=LO(j))c[j]+=a[i];
          int j;j=i+1;
           for(j;j<=n;j+=LO(j))c[j]-=a[i];
          }
        for(int j=1;j<=m;j++){
          int s;
          scanf("%d",&s);
         if(s==1){int k1,k2,k3;
            scanf("%d%d%d",&k1,&k2,&k3);
            F(k1,k2,k3);
         }
         else{int k;
              scanf("%d",&k);
              F(k);
              printf("
    ");
         }
        }
        return 0;
    }
    P3368 【模板】树状数组 2

    查分树状数组


    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #define ll long long
    using namespace std;
    const int maxn=10000+2333;
    const ll mod=23333333333ll;
    const int sand=107;
    char ch[maxn];
    ll a[maxn];
    ll hax(){
        int len=strlen(ch);
        ll re=0;
        for(int i=0;i<len;i++)re=(re*sand+ch[i])%mod;
        return re;
    }
    int n; 
    int main(){
        ios::sync_with_stdio(0);
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>ch;
            a[i]=hax();
        }
        sort(a+1,a+1+n);
        int tot=unique(a+1,a+1+n)-a-1;
        cout<<tot;
        return 0;
    }
    【模板】字符串哈希

    哈希判断是否重复,wa了该取模数。O2之后某个溢出哈希就会挂~(≧▽≦)/~啦啦啦


    最短路

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<queue>
    #include<algorithm>
    #include<cstring>
    #define _X .first 
    #define _Y .second 
    #define ll long long
    using namespace std;
    const int maxn=10000+2333;
    inline int read(){
        int an=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=an*10+ch-'0';ch=getchar();}
        return an*f;
    }
    int n,m,S,cnt;
    int f[maxn];
    ll dis[maxn];
    pair<ll,int>now;
    priority_queue<pair<ll,int> >q;
    struct saber{
    int nex,to,wi;
    }b[(500000<<1)+233];
    inline void add(int x,int y,int z){
        cnt++;
        b[cnt].wi=z;
        b[cnt].to=y;
        b[cnt].nex=f[x];
        f[x]=cnt;
    }
    void dij(){
        for(int i=1;i<=n;i++)dis[i]=2147483647;
        dis[S]=0;
        q.push(make_pair(0,-S));
        while(!q.empty()){
            now=q.top();q.pop();
            int x=-now _Y;
            for(int i=f[x];i;i=b[i].nex){
                int v=b[i].to;
                if(dis[v]>dis[x]+b[i].wi){
                    dis[v]=dis[x]+b[i].wi;
                    q.push(make_pair(-dis[v],-v));
                }
            }
        }
    }
    int main(){
        n=read();m=read();S=read();
        for(int i=1;i<=m;i++){
            int x=read(),y=read(),z=read();
            add(x,y,z);
        }
        dij();
        for(int i=1;i<=n;i++)
        cout<<dis[i]<<" ";
        return 0;
    }
    dijkstra

    传说他稳定

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<queue>
    #include<algorithm>
    #define ll long long 
    using namespace std;
    const ll INT=2147483647LL;
    ll read(){
        ll an=0,f=1;
        char ch=getchar();
        while(!('0'<=ch&&ch<='9')){if(ch=='-')f=-1;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=an*10+ch-'0';ch=getchar();}
        return an*f;
    }
    ll x,y,z;
    ll f[10000+99],spf[10000+99],m,n,k,wi[500099],sum;
    bool cx[10000+99];
    queue<ll>q;
    struct saber{
    int nex,to;
    }b[500099];
    void add(ll x,ll y,ll z){
        sum++;
        b[sum].nex=f[x];
        b[sum].to=y;
        f[x]=sum;
        wi[sum]=z;
    }
    void spfa(){
        while(!q.empty()){
            ll v=q.front();
            q.pop();cx[v]=0;
            for(int i=f[v];i;i=b[i].nex){
                if(spf[b[i].to]>spf[v]+wi[i]){
                spf[b[i].to]=spf[v]+wi[i];
                if(!cx[b[i].to]){
                    q.push(b[i].to);
                    cx[b[i].to]=1;}
                }
            }
        }
    }
    int main(){
        n=read();m=read();k=read();
        for(int i=0;i<=n;i++)spf[i]=INT;
        for(int i=1;i<=m;i++){
            x=read();y=read(),z=read();
            add(x,y,z);}
        q.push(k);spf[k]=0;
        cx[k]=1;
        spfa();
        for(int i=1;i<=n;i++)cout<<spf[i]<<" ";
        return 0;
    }
    SPFA

    不知道双向队列那个快?[>_<]


    线段树模板

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    #include<cstring> 
    #define ll long long
    using namespace std;
    const ll maxn=100000+233;
    inline ll read(){
        ll an=0,f=1;
        char ch=getchar();
        while(ch<'0'||'9'<ch){ch=getchar();}
        while('0'<=ch&&ch<='9'){an=(an<<1)+(an<<3)+(ch^48);ch=getchar();}
        return an;
    }
    struct saber{
    ll l,r,lazy,sum;
    }t[maxn<<4];
    ll n,m; 
    inline void build(ll k,ll l,ll r){
        t[k].l=l;t[k].r=r;
        if(l==r){t[k].sum=read();return;}
        ll mid=l+r>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
    }
    inline void change(ll k){
        ll x=t[k].r+1-t[k].l;
        t[k<<1].lazy+=t[k].lazy;
        t[k<<1|1].lazy+=t[k].lazy;
        t[k<<1].sum+=t[k].lazy*(x+1>>1);
        t[k<<1|1].sum+=t[k].lazy*(x>>1);
        t[k].lazy=0;
    } 
    inline ll ask(ll k,ll x,ll y){
        ll l=t[k].l,r=t[k].r;
        if(t[k].lazy)change(k);
        if(y==r&&l==x){return t[k].sum;}
        ll mid=l+r>>1;
        if(y<=mid)return ask(k<<1,x,y);
        else if(mid<x)return ask(k<<1|1,x,y);
        else return ask(k<<1,x,mid)+ask(k<<1|1,mid+1,y);
    }
    inline void add(ll k,ll x,ll y,ll wi){
        if(t[k].lazy)change(k);
        ll l=t[k].l,r=t[k].r;
        if(y==r&&l==x){t[k].sum+=(r-l+1)*wi;t[k].lazy+=wi;return;}
        ll mid=l+r>>1;
        if(y<=mid)add(k<<1,x,y,wi);
        else if(mid<x)add(k<<1|1,x,y,wi);
        else {add(k<<1,x,mid,wi);add(k<<1|1,mid+1,y,wi);}
        t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
    }
    int main(){
        n=read();m=read();
        build(1,1,n);
        for(;m;m--){
            ll pd=read(),x=read(),y=read();
            if(pd==1){
                ll v=read();
                add(1,x,y,v);
            }
            else {
                cout<<ask(1,x,y)<<"
    ";
            }
        }
    }
    线段树
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath> 
    #define ll long long
    using namespace std;
    inline ll read(){
        ll an=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){ch=getchar();}
        while('0'<=ch&&ch<='9'){an=(an<<3)+(an<<1)+(ch^48);ch=getchar();}
        return an;
    } 
    const ll maxn=100000+233;
    ll link[maxn],a[maxn],b[3000],size,add[3000],block,n,m,l[3000],r[3000];
    int main(){
        ios::sync_with_stdio(0);
        n=read();m=read();
        size=sqrt(n);
        l[1]=1;
        for(ll i=1;i<=n;i++)a[i]=read();
        for(ll i=1;i<=n;i++){
            link[i]=block+1;
            b[block+1]+=a[i];
            if(!(i%size)){
                block++;
                l[block+1]=i+1;
                r[block]=i;
            }
        }
        if(n%size)r[++block]=n;
        for(;m;m--){
            ll pd=read();
            if(pd==1){
                ll L=read(),R=read(),p=read();
                ll chl=link[L],chr=link[R];
                if(chl^chr){
                    for(ll i=L;i<=r[chl];i++)a[i]+=p,b[chl]+=p;
                    for(ll i=l[chr];i<=R;i++)a[i]+=p,b[chr]+=p;
                    for(ll i=chl+1;i<chr;i++)add[i]+=p;
                }
                else{
                    for(ll i=L;i<=R;i++)a[i]+=p;
                }
            }
            else {
                ll ans=0,L=read(),R=read();
                ll chl=link[L],chr=link[R];
                if(chl^chr){
                    for(ll i=L;i<=r[chl];i++)ans+=add[chl]+a[i];
                    for(ll i=l[chr];i<=R;i++)ans+=add[chr]+a[i];
                    for(ll i=chl+1;i<chr;i++)ans+=add[i]*(r[i]-l[i]+1)+b[i];
                }
                else{
                    for(ll i=L;i<=R;i++)ans+=a[i]+add[i];
                }
                cout<<ans<<"
    ";
            }
        }
    }
    分块

    分块还是好写


    【模板】树状数组 1

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    #define IN 5999620
    int a[IN],c[IN];
    int LO(int x){return (-x)&x;}
    int m,n;
    int q,w,e;
    void FF(int x,int y){
           for(int k=x;k<=n;k+=LO(k))
           c[k]+=y;
    }
    int S(int s){int ans=0;
        for(int j=s;j>0;j-=LO(j))
        ans+=c[j];
        return ans;
    }
    void FFF(int i,int j){
            cout<<S(j)-S(i)<<endl;
    }
    int main(){
        cin>>n>>m;
        for(int i=1;i<=n;i++){scanf("%d",&a[i]);
         for(int j=i;j<=n;j+=LO(j))
          c[j]+=a[i];}
         for(int i=1;i<=m;i++){
         scanf("%d%d%d",&q,&w,&e);
          if(q==1)FF(w,e);
          else FFF(w-1,e);
         }
         return 0;
    }
    树状数组

    就是2去掉差分


    【模板】堆

    手打堆

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    inline int read(){
        int an=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=(an<<3)+(an<<1)+ch-48;ch=getchar();}
        return an*f;
    }
    const int maxn=100000+23;
    using namespace std;
    int q;
    int t[maxn],tot;
    inline void add(int x){
        tot++;
        t[tot]=x;
        for(int i=tot,j=i>>1;j;i=j,j=i>>1){
            if(t[j]>t[i])swap(t[i],t[j]);
        }
    }
    inline void pop(){
        t[1]=t[tot];tot--;
        for(int i=1,j=i<<1;j<=tot;i=j,j=i<<1){
            if(j+1<=tot&&t[j+1]<t[j])
            ++j;
            if(t[i]<t[j])break;
            else swap(t[i],t[j]);
        }
    }
    inline int getans(){
        return t[1];
    }
    int main(){
        q=read();
        ios::sync_with_stdio(0);
        while(q){
            q--;
            int x=read();
            if(x==1)add( read() );
            else if(x==2)cout<<getans()<<"
    ";
            else pop();
        }
    }

    【模板】最近公共祖先(LCA)

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    int read(){
        int an=0,f=1;
        char ch=getchar();
        while(!('0'<=ch&&ch<='9')){if(ch=='-')f=-f;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=an*10+ch-'0';ch=getchar();}
        return f*an;
    }
    const int maxn=500000+999;
    int n,m,s,cnt;
    int f[maxn],fa[maxn][25],deep[maxn];
    bool vis[maxn];
    int x,y;
    struct saber{
    int nex,to;
    }b[maxn*2];
    void add(int x,int y){
        cnt++;
        b[cnt].nex=f[x];
        b[cnt].to=y;
        f[x]=cnt;}
    void dfs(int x){
        vis[x]=1;
        for(int i=f[x];i;i=b[i].nex){
            int v=b[i].to;
            if(!vis[v]){
                fa[v][0]=x;deep[v]=deep[x]+1;
            for(int j=1;j<=20;j++){
                if(!fa[fa[v][j-1]][j-1])break;
                fa[v][j]=fa[fa[v][j-1]][j-1];}
                dfs(v);
            }
        }
    }
    int lca(int u,int v){
        if(deep[u]>deep[v])swap(u,v);
        for(int i=20;i>=0;i--)
            if(deep[fa[v][i]]>=deep[u])v=fa[v][i];
        if(u==v)return u;
        for(int i=20;i>=0;i--)
            if(fa[u][i]!=fa[v][i])u=fa[u][i],v=fa[v][i];
        if(u==v)return u;
        return fa[u][0];
    }
    void Lca(int x,int y){
        int ans=lca(x,y);
        printf("%d
    ",ans);
    }
    int main(){
        n=read();m=read();s=read();
        for(int i=1;i<n;i++){
            x=read();y=read();
            add(x,y);add(y,x);}
        deep[s]=1;
        dfs(s);
        for(int i=1;i<=m;i++){
            x=read();y=read();
            Lca(x,y);}
        return 0;
    }
    倍增
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<queue>
    #include<algorithm>
    using namespace std;
    int read(){
        int an=0,f=1;char ch=getchar();
        while(!('0'<=ch&&ch<='9')){if(ch=='-')f=-f;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=an*10+ch-'0';ch=getchar();}
        return an*f;
    }
    int n,m,s,cnt,qf[500099],f[500099],fa[500099],ans[500099<<1];
    int x,y;
    bool vis[500099];
    int found(int x){
        if(fa[x]!=x)fa[x]=found(fa[x]);
        return fa[x];}
    struct saber{
    int to,nex;
    }b[500099<<1];
    struct question{
    int to,nex;
    }qu[500099<<1];
    void add(int x,int y){
        cnt++;b[cnt].to=y;
        b[cnt].nex=f[x];f[x]=cnt;
    }
    void add(int x,int y,int z){
        qu[z].to=y;
        qu[z].nex=qf[x];
        qf[x]=z;
    }
    void dfs(int x){
        fa[x]=x;vis[x]=1;
        for(int i=f[x];i;i=b[i].nex){
            int v=b[i].to;
            if(!vis[v]){
                dfs(v);
                fa[v]=x;
            }
        }
        for(int i=qf[x];i;i=qu[i].nex){
            int v=qu[i].to;
            if(vis[v]){
                ans[i]=found(v);
                if(i&1)ans[i+1]=ans[i];
                else ans[i-1]=ans[i];
            }
        }
    }
    int main(){
        n=read();m=read();s=read();
        for(int i=1;i<n;i++){
            int x,y;x=read();y=read();
            add(x,y);add(y,x);
        }
        for(int i=1;i<=m;i++){
            x=read();y=read();
            add(x,y,(i<<1)-1);add(y,x,(i<<1));
        }
        dfs(s);
        for(int i=1;i<=m;i++){
            printf("%d
    ",ans[i<<1]);}
        return 0;
    }
    tarjian

    【模板】网络最大流

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<cstring> 
    const int maxn=100000+2333;
    const int maxm=100000+99999;
    const int INT=1e7;
    using namespace std;
    inline int read(){
        int an=0,f=1;
        char ch=getchar();
        while(ch<'0'||'9'<ch){ch=getchar();}
        while('0'<=ch&&ch<='9'){an=(an<<1)+(an<<3)+(ch^48);ch=getchar();}
        return an;
    }
    int f[maxn],S,T,n,m,cnt=1;
    struct saber{
    int wi,nex,to;
    }b[maxn<<2];
    inline void add(int x,int y,int z){
        cnt++;
        b[cnt].to=y;
        b[cnt].wi=z;
        b[cnt].nex=f[x];
        f[x]=cnt;
    }
    queue<int>q;
    int dis[maxn];
    bool vis[maxn];
    inline int bfs(){
        while(!q.empty())q.pop();
        q.push(S);
        memset(dis,-1,sizeof dis);
        dis[S]=0;
        while(!q.empty()){
            int x=q.front();q.pop();
            for(int i=f[x];i;i=b[i].nex){
                int v=b[i].to;
                if(dis[v]<0&&b[i].wi){
                    dis[v]=dis[x]+1;
                    if(v==T)return 1;
                    q.push(v);
                }
            }
        } 
        return 0;
    }
    inline int dfs(int x,int li){
        if(x==T||!li)return li;
        int used=li;
        vis[x]=1;
        for(int i=f[x];i;i=b[i].nex){
            int v=b[i].to;
            if(!vis[v]){
                if(dis[v]==dis[x]+1&&used&&b[i].wi){
                    int re=dfs(v,min(b[i].wi,used));
                    used-=re;
                    b[i].wi-=re;
                    b[i^1].wi+=re;
                }
            }
        }
        return li-used;
    }
    void dinic(){
        int ans=0;
        while(bfs()){
            memset(vis,0,sizeof vis);
            ans+=dfs(S,INT);
        }
        cout<<ans;
    }
    int main(){
        n=read();m=read();S=read();T=read();
        for(int i=1;i<=m;i++){
            int x=read(),y=read(),z=read();
            add(x,y,z);
            add(y,x,0);
        } 
        dinic();
        return 0;
    }
    网络流

    真noip


    【模板】最小费用最大流

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #include<cstring> 
    const int maxn=100000+2333;
    const int maxm=100000+99999;
    const int INT=1e7;
    using namespace std;
    inline int read(){
        int an=0,f=1;
        char ch=getchar();
        while(ch<'0'||'9'<ch){ch=getchar();}
        while('0'<=ch&&ch<='9'){an=(an<<1)+(an<<3)+(ch^48);ch=getchar();}
        return an;
    }
    int f[maxn],S,T,n,m,cnt=1;
    struct saber{
    int wi,nex,to,fi;
    }b[maxn<<2];
    inline void add(int x,int y,int z,int fi){
        cnt++;
        b[cnt].to=y;
        b[cnt].wi=z;
        b[cnt].fi=fi;
        b[cnt].nex=f[x];
        f[x]=cnt;
    }
    deque<int>q;
    int dis[maxn];
    bool vis[maxn],in[maxn];
    inline int bfs(){
        while(!q.empty())q.pop_front();
        q.push_back(S);
        for(int i=0;i<=n+2;i++)dis[i]=INT;
        memset(in,0,sizeof in);
        dis[S]=0;
        while(!q.empty()){
            int x=q.front();q.pop_front();in[x]=0;
            for(int i=f[x];i;i=b[i].nex){
                int v=b[i].to;
                if(dis[v]>dis[x]+b[i].fi&&b[i].wi){
                    dis[v]=dis[x]+b[i].fi;
                    if(!in[v]){
                    in[v]=1;
                    if(!q.empty()&&dis[v]<dis[q.front()])q.push_front(v);
                    else q.push_back(v);
                    } 
                }
            }
        }
        return dis[T]<INT;
    }
    inline int dfs(int x,int li){
        if(x==T||!li)return li;
        int used=li;
        vis[x]=1;
        for(int i=f[x];i;i=b[i].nex){
            int v=b[i].to;
            if(!vis[v]){
                if(dis[v]==dis[x]+b[i].fi&&used&&b[i].wi){
                    int re=dfs(v,min(b[i].wi,used));
                    used-=re;
                    b[i].wi-=re;
                    b[i^1].wi+=re;
                }
            }
        }
        return li-used;
    }
    void dinic(){
        int ans=0;
        int fe=0;
        while(bfs()){
            memset(vis,0,sizeof vis);
            int v=dfs(S,INT);
            ans+=v;
            fe+=dis[T]*v;
        }
        cout<<ans<<" "<<fe;
    }
    int main(){
        n=read();m=read();S=read();T=read();
        for(int i=1;i<=m;i++){
            int x=read(),y=read(),z=read(),fi=read();
            add(x,y,z,fi);
            add(y,x,0,-fi);
        }
        dinic();
        return 0;
    }
    费用流

    在网络流上加最短路


    【模板】负环

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #define ll long long
    using namespace std;
    const int maxn=200000+2333; 
    inline int read(){
        int an=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=an*10+ch-'0';ch=getchar();}
        return an*f;
    }
    struct saber{
    int nex,wi,to;
    }b[maxn<<1];
    int f[maxn],dis[maxn],T,cnt,n,m,flag;
    bool vis[maxn];
    inline void add2(int x,int y,int z){
        cnt++;
        b[cnt].to=y;
        b[cnt].wi=z;
        b[cnt].nex=f[x];
        f[x]=cnt;
    }
    inline void add(int x,int y,int z){
        if(z>0)add2(x,y,z),add2(y,x,z);
        else add2(x,y,z);
    }
    inline void dfs(int x){
        if(vis[x]){flag=1;return ;}
        vis[x]=1;
        for(int i=f[x];i&&!flag;i=b[i].nex){
            int v=b[i].to;
            if(dis[v]>dis[x]+b[i].wi){
                dis[v]=dis[x]+b[i].wi;
                dfs(v);
            }
        }
        vis[x]=0;
    }
    int main(){
        T=read();
        ios::sync_with_stdio(0);
        while(T){T--;
            flag=0;
            cnt=0;
            memset(vis,0,sizeof vis);
            memset(dis,0,sizeof dis);
            memset(f,0,sizeof f);
            n=read();m=read();
            for(int i=1;i<=m;i++){
                int x=read(),y=read(),z=read();
                add(x,y,z);
            }
            for(int i=1;i<=n&&!flag;i++){
                dfs(i);
            }
            if(!flag)cout<<"N0
    ";
            else cout<<"YE5
    ";
        }
    }
    负环

    dfs判负环


    【模板】二分图匹配

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #define ll long long
    using namespace std;
    const int maxn=3000;
    inline int read(){
        int an=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=(an<<3)+(an<<1)+ch-'0';ch=getchar();}
        return an*f;
    }
    int f[maxn<<1],ans,cnt,n,m,e;
    struct saber{
    int nex,to;
    }b[5000000];
    inline void add(int x,int y){
        cnt++;
        b[cnt].to=y;
        b[cnt].nex=f[x];
        f[x]=cnt;
    }
    int in[maxn<<1];
    bool vis[maxn<<1];
    inline int dfs(int x){
        for(int i=f[x];i;i=b[i].nex){
            int v=b[i].to;
            if(!in[v]){in[v]=x;return 1;}
        }
        for(int i=f[x];i;i=b[i].nex){
            int v=b[i].to;
            if(vis[v])continue;
            vis[v]=1;
            if(dfs(in[v])){in[v]=x;return 1;}
        }
        return 0;
    }
    int main(){
        n=read();m=read();e=read();
        for(int i=1;i<=e;i++){
        int x=read(),y=read();
            if(y>m);
            else add(x,n+10+y);
        }
        for(int i=1;i<=n;i++){
        memset(vis,0,sizeof vis);
        if(dfs(i))ans++;
        }
        cout<<ans;
    }
    匈牙利算法

    莫名其妙<网络流跑不A(竟然不是T


    【模板】缩点

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<stack>
    #define ll long long
    using namespace std;
    const int maxn=1e4+233+17+9;
    const int maxm=1e5+2333+17+9+4950;
    inline int read(){
        int an=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=(an<<3)+(an<<1)+ch-'0';ch=getchar();}
        return an*f;
    }
    int scc,f[maxn],ff[maxn],id;
    int dag[maxn],dfn[maxn],low[maxn],wi[maxn];
    int bel[maxn];
    int dp[maxn],cnt,ans,n,m,ins[maxn];
    bool vis[maxn],in[maxn];
    struct saber{
    int nex,to;
    }b[maxm],bb[maxm];
    stack<int>s;
    inline void add(int x,int y){
        cnt++;
        b[cnt].to=y;
        b[cnt].nex=f[x];
        f[x]=cnt;
    }
    inline void add2(int x,int y){
        cnt++;
        ins[y]++;
        bb[cnt].to=y;
        bb[cnt].nex=ff[x];
        ff[x]=cnt;
    }
    inline void dfs(int x){
        id++;
        dfn[x]=low[x]=id;
        in[x]=vis[x]=1;
        s.push(x);
        for(int i=f[x];i;i=b[i].nex){
            int v=b[i].to;
            if(!vis[v]){
                dfs(v);
                low[x]=min(low[x],low[v]);
            }
            else if(in[v])low[x]=min(low[x],dfn[v]);
        }
        if(dfn[x]==low[x]){
            int z=22333;scc++;
            while(z!=x){
                z=s.top();
                bel[z]=scc;
                dag[scc]+=wi[z];
                in[z]=0;
                s.pop();
            }
        }
    }
    queue<int>q;
    inline void rebuild(){
        cnt=1;
        for(int i=1;i<=n;i++){
            for(int j=f[i];j;j=b[j].nex){
                int v=b[j].to;
                if(bel[i]!=bel[v])add2(bel[i],bel[v]);
            }
        }
    }
    inline void top_sort(){
        int flag,l=1;
        while(l<=n){
        memset(vis,0,sizeof vis);
        memset(dp,0,sizeof dp);
        while(l<=n){
        if(!ins[l]){q.push(l);flag=l;break;}
        else l++;
        }
        dp[flag]=dag[flag];
        while(!q.empty()){
            int x=q.front();q.pop();vis[x]=0;
            for(int i=ff[x];i;i=bb[i].nex){
                int v=bb[i].to;
                if(dp[v]<dp[x]+dag[v]){
                dp[v]=dp[x]+dag[v];
                if(!vis[v]){
                    q.push(v);
                    vis[v]=1;
                        }
                        }
                }
            ans=max(ans,dp[x]);
            }
            l=l+1;
            }
    }
    int main(){
        n=read();m=read();
        for(int i=1;i<=n;i++)wi[i]=read();
        for(int i=1;i<=m;i++){
            int x=read(),y=read();
            add(x,y);
        }
        for(int i=1;i<=n;i++)
        if(!vis[i])dfs(i);
        rebuild();
        top_sort();
        cout<<ans;
        return 0;    
    }
    dp

    不要跑最短路>>


    【模板】割点(割顶)

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<stack>
    #define ll long long
    using namespace std;
    const int maxn=100000+2333+17+9+4950;
    inline int read(){
        int an=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=(an<<3)+(an<<1)+ch-'0';ch=getchar();}
        return an*f;
    }
    int f[maxn],n,m,cnt=1,id;
    bool cut[maxn],vis[maxn];
    int dfn[maxn],low[maxn],ans;
    struct saber{
    int nex,to;
    }b[maxn<<1];
    inline void add(int x,int y){
        cnt++;
        b[cnt].to=y;
        b[cnt].nex=f[x];
        f[x]=cnt;
    }
    inline int dfs(int x,int fa){
        int sum=0;bool cu=0;
        id++;
        dfn[x]=low[x]=id;vis[x]=1;
        for(int i=f[x];i;i=b[i].nex){
            int v=b[i].to;
            if(v==fa)continue;
            if(!vis[v]){
                sum++;
                dfs(v,x);
                low[x]=min(low[x],low[v]);
                if(low[v]>=dfn[x])cu=1;
            }
            else low[x]=min(low[x],dfn[v]);
        }
        if(!fa){if(sum>1)ans++,cut[x]=1;}
        else if(cu)ans++,cut[x]=1;
    }
    int main(){
        n=read();m=read();
        for(int i=1;i<=m;i++){
            int x=read(),y=read();
            add(x,y);add(y,x);
        }
        for(int i=1;i<=n;i++)
        if(!vis[i])dfs(i,0);
        cout<<ans<<"
    ";
        for(int i=1;i<=n;i++)if(cut[i])cout<<i<<" ";
        return 0;
    }
    割点

    贪心,先找根,然后判下面是否割


    【模板】卢卡斯定理

    #include<iostream>
    #include<cstdlib>
    #define ll long long 
    using namespace std;
    ll T,p;
    ll f[500000];
    ll ks(ll y,ll k){
        ll s=y,ans=1;
        while(k){
            if(k&1)ans=ans*s%p;
            s=s*s%p;
            k>>=1;
        }
        return ans%p;
    }
    ll C(ll n,ll m){
        if(m>n)return 0;
        return f[n]*ks(f[m]*f[n-m],p-2)%p;
    }
    ll Luc(ll n,ll m){
        if(!m)return 1;
        return (Luc(n/p,m/p)*C(n%p,m%p))%p;
    }
    int main(){
        cin>>T;
        while(T){
        ll n,m;
        T--;
        cin>>n>>m>>p;
        f[0]=1;
        for(int i=1;i<=p;i++)f[i]=f[i-1]*i%p;
        cout<<Luc(n+m,m)<<endl;}
        return 0;
    }
    组合数

    数论


    【模板】ST表

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    const int maxn=100000+999;
    int read(){
        int f=1,an=0;
        char ch=getchar();
        while(!('0'<=ch&&ch<='9')){if(ch=='-')f=-f;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=an*10+(ch-'0');ch=getchar();}
        return an*f;
    }
    int x,y,n,m;
    struct saber{
    int l,r,M;
    }tr[maxn*4+999];
    int a[maxn];
    void build(int k,int l,int r){
        int mid=(l+r)>>1;
        tr[k].l=l;tr[k].r=r;
        if(l==r){tr[k].M=a[l];return;}
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        tr[k].M=max(tr[k<<1].M,tr[k<<1|1].M);
    }
    int ask(int k,int i,int j){
        int l=tr[k].l,r=tr[k].r;
        if(l==i&&j==r){
            return tr[k].M;}
        int mid=(l+r)>>1;
        if(j<=mid){return ask(k<<1,i,j);}
        else if(i>mid){return ask(k<<1|1,i,j);}
        else {return max(ask(k<<1,i,mid),ask(k<<1|1,mid+1,j));}
    }
    int main(){
        n=read();m=read();
        for(int i=1;i<=n;i++)a[i]=read();
        build(1,1,n);
        for(int i=1;i<=m;i++){
            x=read();y=read();
            printf("%d
    ",ask(1,x,y));
        }
        return 0;
    }
    线段树
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    using namespace std;
    const int maxn=1e5+2333;
    inline int read(){
        int an=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while('0'<=ch&&ch<='9'){an=an*10+ch-'0';ch=getchar();}
        return an*f;
    }
    int st[maxn][20],n,q;
    int main(){
        ios::sync_with_stdio(0);
        n=read();q=read();
        for(int i=1;i<=n;i++)st[i][0]=read();
        for(int j=1;j<=20;j++)
        for(int i=1;i+(1<<j-1)-1<=n;i++)
        st[i][j]=max(st[i][j-1],st[i+(1<<j-1)][j-1]);
        while(q){q--;
            int l=read(),r=read();
            int k=log2(r-l+1);
            cout<<max(st[l][k],st[r-(1<<k)+1][k])<<"
    ";
        }
        return 0;
    }
    st

    【模板】矩阵快速幂

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    typedef long long ll;
    using namespace std;
    
    ll n,m,i,j,k;
    
    struct Matrix{
        ll a[105][105];
        inline Matrix operator *(const Matrix &b)const
        {
            Matrix ret;
            for (ll i=1;i<=n;i++)
                for (ll j=1;j<=n;j++)
                {
                    ret.a[i][j]=0;
                    for (ll k=1;k<=n;k++)
                        ret.a[i][j]+=a[i][k]*b.a[k][j],ret.a[i][j]%=1000000007;
                }
            return ret;
        }
    }a;
    
    inline ll read()
    {
        ll iep=1,ret=0;char ch=getchar();
        while (ch<'0'||ch>'9'){if (ch=='-') iep=-1;ch=getchar();}
        while (ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
        return ret*iep;
    }
    
    Matrix ksm(Matrix a,ll x)
    {
        Matrix ret,k;k=a;
        ret=a;x--;
        for (;x;x>>=1,k=k*k)
            if (x&1) ret=ret*k;
        return ret;
    }
    
    int main()
    {
        n=read();k=read();
        for (i=1;i<=n;i++)
            for (j=1;j<=n;j++)
                a.a[i][j]=read();
        a=ksm(a,k);
        for (i=1;i<=n;i++)
        {
            for (j=1;j<n;j++) printf("%d ",a.a[i][j]);
            printf("%d
    ",a.a[i][n]);
        }
    }
    QAQ

    想当初不会啊

  • 相关阅读:
    Rex 密钥认证
    MQTT协议之moquette 安装使用
    开源MQTT中间件:moquette
    Hazelcast入门简介
    Maven和Gradle对比
    rex 上传文件并远程执行
    myeclipse配置gradle插件
    ansible 新手上路
    CentOS release 6.5 (Final) 安装ansible
    spring boot 使用profile来分区配置
  • 原文地址:https://www.cnblogs.com/ck666/p/7813188.html
Copyright © 2020-2023  润新知