• 20191012


    A.

    SB平衡树拆点题
    常数巨大

    Code

    #pragma GCC optimize("-fdelete-null-pointer-checks,inline-functions-called-once,-funsafe-loop-optimizations,-fexpensive-optimizations,-foptimize-sibling-calls,-ftree-switch-conversion,-finline-small-functions,inline-small-functions,-frerun-cse-after-loop,-fhoist-adjacent-loads,-findirect-inlining,-freorder-functions,no-stack-protector,-fpartial-inlining,-fsched-interblock,-fcse-follow-jumps,-fcse-skip-blocks,-falign-functions,-fstrict-overflow,-fstrict-aliasing,-fschedule-insns2,-ftree-tail-merge,inline-functions,-fschedule-insns,-freorder-blocks,-fwhole-program,-funroll-loops,-fthread-jumps,-fcrossjumping,-fcaller-saves,-fdevirtualize,-falign-labels,-falign-loops,-falign-jumps,unroll-loops,-fsched-spec,-ffast-math,Ofast,inline,-fgcse,-fgcse-lm,-fipa-sra,-ftree-pre,-ftree-vrp,-fpeephole2",3)
    #include<bits/stdc++.h>
    #define L(p) t[p].son0
    #define R(p) t[p].son1
    using namespace std;
    typedef long long D;
    const int maxn=500003;
    struct node{
        int son0,son1,sz,tot,len;
        bool z;
        D sum,s,zs;
    }t[maxn];
    int cnt,root;
    int new_node(int len){
        t[++cnt]=(node){0,0,1,len,len,0,0,0};
        return cnt;
    }
    void pushup(int p){
        t[p].sz=t[L(p)].sz+t[R(p)].sz+1;
        t[p].tot=t[L(p)].tot+t[R(p)].tot+t[p].len;
        t[p].sum=t[L(p)].sum+t[R(p)].sum+t[p].s;
    }
    void solve1(int p){if(p)swap(L(p),R(p)),t[p].z^=1;}
    void solve2(int p,D z){if(p)t[p].s+=z*t[p].len,t[p].sum+=z*t[p].tot,t[p].zs+=z;}
    void pushdown(int p){
        if(t[p].z){
            solve1(L(p)),solve1(R(p));
            t[p].z=0;
        }
        if(t[p].zs){
            solve2(L(p),t[p].zs),solve2(R(p),t[p].zs);
            t[p].zs=0;
        }
    }
    void output(int p){
        if(!p)return;
    //  pushdown(p);
        output(L(p));
    printf("p:%d son0:%d son1:%d sz:%d tot:%d len:%d sum:%lld s:%lld z:%d zs:%lld
    ",p,t[p].son0,t[p].son1,t[p].sz,
    t[p].tot,t[p].len,t[p].sum,t[p].s,t[p].z,t[p].zs);
        output(R(p));
    }
    void O(int p=root){
        printf("BEGINBEGINBEGIN root:%d
    ",root);
        output(p);
        printf("ENDENDENDENDEND
    ");
    }
    void splitsz(int p,int k,int &x,int &y){
        if(p==0){x=y=0;return;}
        pushdown(p);
        if(t[L(p)].sz+1<=k){
            x=p;
            splitsz(R(p),k-t[L(p)].sz-1,R(p),y);
        }
        else{
            y=p;
            splitsz(L(p),k,x,L(p));
        }
        pushup(p);
    }
    void splittot(int p,int k,int &x,int &y){
        if(p==0){x=y=0;return;}
        pushdown(p);
        if(t[L(p)].tot+t[p].len<=k){
            x=p;
            splittot(R(p),k-t[L(p)].tot-t[p].len,R(p),y);
        }
        else{
            y=p;
            splittot(L(p),k,x,L(p));
        }
        pushup(p);
    }
    void merge(int &p,int x,int y){
        if(x==0||y==0){p=x+y;return;}
        if(rand()%(t[x].sz+t[y].sz)<t[x].sz){
            pushdown(x);
            merge(R(x),R(x),y);
            pushup(x);
            p=x;
        }
        else{
            pushdown(y);
            merge(L(y),x,L(y));
            pushup(y);
            p=y;
        }
    }
    void rev(int l,int r){
        int x,y,z;
        splittot(root,l-1,x,y);
        splittot(y,r-l+1,y,z);
        solve1(y);
        merge(y,x,y);
        merge(root,y,z);
    }
    void add(int l,int r,D k){
        int x,y,z;
        splittot(root,l-1,x,y);
        splittot(y,r-l+1,y,z);
        solve2(y,k);
        merge(y,x,y);
        merge(root,y,z);
    }
    D query(int l,int r){
        int x,y,z;
        splittot(root,l-1,x,y);
        splittot(y,r-l+1,y,z);
        D ret=t[y].sum;
        merge(y,x,y);
        merge(root,y,z);
        return ret;
    }
    void splnode(int i){ //[l,r] -> [l,i-1], [i,r]
        int x,p1,p2,z;
        splittot(root,i-1,x,p1);
        splitsz(p1,1,p1,z);
        int l=t[x].tot+1,r=t[x].tot+t[p1].len;
        if(i>l&&i<=r){
            t[p1].len=i-l;
            p2=new_node(r-i+1);
            t[p2].s=t[p1].s/(r-l+1)*(r-i+1);
            t[p1].s=t[p1].s/(r-l+1)*(i-l);
            pushup(p1),pushup(p2);
            merge(p1,p1,p2);
        }
        merge(x,x,p1);
        merge(root,x,z);
    }
    int main(){
        srand(19260817);
        int n,Q,ty,mo;
        D l,r,k,last=0;
        scanf("%d%d%d",&n,&Q,&ty);
        n++;
        merge(root,root,new_node(n));
        while(Q--){
            scanf("%d%lld%lld",&mo,&l,&r);
            if(ty)l^=last,r^=last;
            splnode(l);
            splnode(r+1);
            if(mo==0){
                scanf("%lld",&k);
                if(ty)k^=last;
                add(l,r,k);
            }
            if(mo==1){
                rev(l,r);
            }
            if(mo==2){
                printf("%lld
    ",last=query(l,r));
            }
        }
        return 0;
    }
    

    B.

    考虑一个合法的集合 (S)(h) 数组中一定是一个极长非减子序列
    先拓扑排序(也可以不用)求出 (h) 数组,然后神奇dp。
    具体方法:
    (v_i) 表示一个极长子序列的贡献,那么答案 (=sum (v_i(sum-v_i))=sum*sum v_i-sum v_i^2)
    转移方程见代码

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1003,maxm=500003,mod=998244353;
    int Plus(int x,int y){return (x+=y)>=mod?x-mod:x;}
    int Minus(int x,int y){return Plus(x,mod-y);}
    void PlusEqual(int &x,int y){if((x+=y)>=mod)x-=mod;}
    int mul(long long x,int y){return x*y%mod;}
    int qpow(int x,int y){
        int ans=1;
        while(y){
            if(y&1)ans=mul(ans,x);
            x=mul(x,x);
            y>>=1;
        }
        return ans;
    }
    const int inv2=qpow(2,mod-2);
    int n,m,a[maxn],h[maxn],deg[maxn],gr[maxn][maxn],pre[maxn][maxn],sum,dp[maxn],dp2[maxn],cnt[maxn],ans;
    bool ok(int j,int i){
        if(h[i]<h[j])return 0;
        return pre[i-1][h[i]]-pre[j][h[i]]-pre[i-1][h[j]-1]+pre[j][h[j]-1]==0;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",a+i),sum+=a[i];
        for(int i=1;i<=m;i++){
            int u,v;
            scanf("%d%d",&u,&v);
            if(u>v)swap(u,v);
            gr[u][v]=1,deg[v]++;
        }
        for(int i=1;i<=n;i++){
            for(int j=i+1;j<=n;j++){
                if(!gr[i][j])gr[j][i]=1,deg[i]++;
            }
            gr[n+1][i]=1,deg[i]++;
            h[i]=1001;
        }
        h[n+1]=1001;
        queue<int> q;
        q.push(n+1);
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=1;i<=n;i++){
                if(gr[u][i]){
                    h[i]=min(h[i],h[u]-1);
                    if(--deg[i]==0)q.push(i);
                }
            }
        }
        for(int i=1;i<=n;i++)pre[i][h[i]]++;
        for(int i=1;i<=n+1;i++){
            for(int j=1;j<=1001;j++){
                pre[i][j]+=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1];
            }
        }
        for(int i=1;i<=n;i++){
            if(ok(0,i)){
                dp[i]=a[i];
                cnt[i]=1;
            }
            for(int j=1;j<i;j++){
                if(ok(j,i)){
                    PlusEqual(dp2[i],mul(dp[i],Plus(dp[j],mul(cnt[j],a[i]))));
                    int tot=mul(mul(cnt[j],Minus(cnt[j],1)),inv2);
                    PlusEqual(dp2[i],Plus(dp2[j],Plus(mul(mul(Minus(cnt[j],1),dp[j]),a[i]),mul(tot,mul(a[i],a[i])))));
                    PlusEqual(dp[i],Plus(dp[j],mul(cnt[j],a[i])));
                    PlusEqual(cnt[i],cnt[j]);
                }
            }
            if(ok(i,n+1)){
                PlusEqual(ans,Minus(mul(dp[i],sum),Minus(mul(dp[i],dp[i]),mul(2,dp2[i]))));
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    

    C.

    重题
    做不来

  • 相关阅读:
    git——学习笔记(一)
    技术大牛的博客//文档
    python——周边
    数据挖掘算法:关联分析二(Apriori)
    数据挖掘算法:关联分析一(基本概念)
    Python入门5(pandas中merge中的参数how)
    Spark入门3(累加器和广播变量)
    Spark入门2(Spark简析)
    Spark入门1(以WordCount为例讲解flatmap和map之间的区别)
    算法入门1(决策树)
  • 原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/11668342.html
Copyright © 2020-2023  润新知