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.

重题
做不来

原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/11668342.html