NOI模拟2

气死了,被吊打了...

考试前去蹲坑了,然后莫名其妙就把T1想出来了,然后搞了个T2的nq乱搞,结果常数太大T飞了,T3好不容易写个部分分还Wa了

T1

对0分段,发现贡献是一段连续区间里的前缀和奇偶性相同的位置,线段树维护扫描线就行

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=5e5+5;
int n,m,a[N],ans[N];
struct Q{int l,r;}q[N];
vector<int> vec[N];
int pre[N],pos[N],las,lst;
struct XDS{
    #define ls x<<1
    #define rs x<<1|1
    int bso[N*4],bse[N*4];
    int odd[N*4],tgo[N*4],eve[N*4],tge[N*4];
    void build(int x,int l,int r){
        if(l==r){
            if(pre[l]&1)bso[x]=1;
            else bse[x]=1;
            return ;
        }
        int mid=l+r>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
        bso[x]=bso[ls]+bso[rs];
        bse[x]=bse[ls]+bse[rs];
    }
    void pushup(int x){
        odd[x]=odd[ls]+odd[rs];
        eve[x]=eve[ls]+eve[rs];
    }
    void pushdown(int x,int l,int r){
        int mid=l+r>>1;
        if(tgo[x]){
            tgo[ls]+=tgo[x];
            odd[ls]+=tgo[x]*bso[ls];
            tgo[rs]+=tgo[x];
            odd[rs]+=tgo[x]*bso[rs];
            tgo[x]=0;
        }
        if(tge[x]){
            tge[ls]+=tge[x];
            eve[ls]+=tge[x]*bse[ls];
            tge[rs]+=tge[x];
            eve[rs]+=tge[x]*bse[rs];
            tge[x]=0;
        }
    }
    void ins_odd(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr){tgo[x]++;odd[x]+=bso[x];return ;}
        int mid=l+r>>1;if(tgo[x]||tge[x])pushdown(x,l,r);
        if(ql<=mid)ins_odd(ls,l,mid,ql,qr);
        if(qr>mid)ins_odd(rs,mid+1,r,ql,qr);
        pushup(x);
    }
    void ins_eve(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr){tge[x]++;eve[x]+=bse[x];return ;}
        int mid=l+r>>1;if(tgo[x]||tge[x])pushdown(x,l,r);
        if(ql<=mid)ins_eve(ls,l,mid,ql,qr);
        if(qr>mid)ins_eve(rs,mid+1,r,ql,qr);
        pushup(x);
    }
    int query(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr)return odd[x]+eve[x];
        int mid=l+r>>1,ret=0;if(tgo[x]||tge[x])pushdown(x,l,r);
        if(ql<=mid)ret+=query(ls,l,mid,ql,qr);
        if(qr>mid)ret+=query(rs,mid+1,r,ql,qr);
        pushup(x);return ret;
    }
    #undef ls
    #undef rs
}xds;
signed main(){
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    n=read();m=read();
    fo(i,1,n)a[i]=read(),pre[i]=pre[i-1]+a[i];
    fo(i,1,m){
        q[i].l=read();q[i].r=read();
        vec[q[i].r].push_back(i);
    }
    xds.build(1,0,n);
    fo(i,1,n){
        if(!a[i]){
            if((pre[i]-pre[las])&1)lst=pos[las];
            las=i;
        }
        if((a[i]&1)&&!pos[las])pos[las]=i;
        // cerr<<i<<" "<<las<<" "<<lst<<endl;
        // cerr<<i<<" ";
        if((pre[i]-pre[las])&1){
            // cerr<<"SB"<<endl;
            if(pre[i]&1)xds.ins_odd(1,0,n,las,i-1);
            else xds.ins_eve(1,0,n,las,i-1);
        }
        else {
            // cerr<<"ZZ"<<endl;
            if(pre[i]&1)xds.ins_odd(1,0,n,lst,i-1);
            else xds.ins_eve(1,0,n,lst,i-1);
        }
        for(int x:vec[i]){
            ans[x]=xds.query(1,0,n,q[x].l-1,q[x].r);
        }
    }
    fo(i,1,m)printf("%lld\n",ans[i]);
    return 0;
}

T2

吉司机线段树,区间min区间和,套上回滚莫队就行了,复杂度不太好保证,能过

AC_code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=15005;
const int M=100005;
const int inf=0x3f3f3f3f;
int n,m,qq,a[N];ll ans[M];
struct CZ{int l,r,x;}cz[N];
struct Q{int l1,r1,l2,r2,id;}q[M];
int sq,bl[N];
bool comQ(Q a,Q b){
    if(bl[a.l1]!=bl[b.l1])return bl[a.l1]<bl[b.l1];
    return a.r1<b.r1;
}
struct XDS{
    #define ls x<<1
    #define rs x<<1|1
    int mx[N*4],cm[N*4],nx[N*4],tg[N*4];ll sm[N*4];
    int ql,qr,v,tp;
    struct STA{
        int mx,cm,nx,id,tg;ll sm;
        STA(){}
        STA(int a,int b,int c,ll d,int e,int f){
            mx=a;cm=b;nx=c;sm=d;id=e;tg=f;
        }
    }sta[M*6];int top;
    void pushup(int x){
        sm[x]=sm[ls]+sm[rs];
        if(mx[ls]==mx[rs]){
            mx[x]=mx[ls];
            cm[x]=cm[ls]+cm[rs];
            nx[x]=max(nx[ls],nx[rs]);
        }
        else if(mx[ls]>mx[rs]){
            mx[x]=mx[ls];
            cm[x]=cm[ls];
            nx[x]=max(mx[rs],nx[ls]);
        }
        else {
            mx[x]=mx[rs];
            cm[x]=cm[rs];
            nx[x]=max(mx[ls],nx[rs]);
        }
    }
    void pushdown(int x){
        if(mx[ls]>tg[x]){
            if(tp)sta[++top]=STA(mx[ls],cm[ls],nx[ls],sm[ls],ls,tg[ls]);
            tg[ls]=tg[x];
            sm[ls]-=1ll*(mx[ls]-tg[x])*cm[ls];
            mx[ls]=tg[x];
        }
        if(mx[rs]>tg[x]){
            if(tp)sta[++top]=STA(mx[rs],cm[rs],nx[rs],sm[rs],rs,tg[rs]);
            tg[rs]=tg[x];
            sm[rs]-=1ll*(mx[rs]-tg[x])*cm[rs];
            mx[rs]=tg[x];
        }
        tg[x]=0;
    }
    void build(int x,int l,int r){
        sm[x]=nx[x]=cm[x]=sm[x]=tg[x]=0;
        if(l==r){
            sm[x]=mx[x]=a[l];cm[x]=1;
            return ;
        }
        int mid=l+r>>1;
        build(ls,l,mid);
        build(rs,mid+1,r);
        pushup(x);
        // cerr<<x<<" "<<l<<" "<<r<<" "<<sm[x]<<endl;
    }
    void rebuild(){
        while(top){
            int id=sta[top].id;
            mx[id]=sta[top].mx;
            cm[id]=sta[top].cm;
            nx[id]=sta[top].nx;
            sm[id]=sta[top].sm;
            tg[id]=sta[top].tg;
            top--;
        }
    }
    void insert(int x,int l,int r){
        if(tp)sta[++top]=STA(mx[x],cm[x],nx[x],sm[x],x,tg[x]);
        if(ql<=l&&r<=qr){
            // cerr<<x<<" "<<l<<" "<<r<<" "<<mx[x]<<" "<<nx[x]<<" "<<v<<endl;
            if(v>=mx[x])return ;
            else if(v>nx[x]&&v<mx[x]){
                sm[x]-=1ll*(mx[x]-v)*cm[x];
                mx[x]=v;tg[x]=v;
            }
            else {
                int mid=l+r>>1;if(tg[x])pushdown(x);
                insert(ls,l,mid);
                insert(rs,mid+1,r);
                pushup(x);
            }
            return ;
        }
        int mid=l+r>>1;if(tg[x])pushdown(x);
        if(ql<=mid)insert(ls,l,mid);
        if(qr>mid)insert(rs,mid+1,r);
        pushup(x);
    }
    void ins(int l,int r,int vl,int tpp){
        ql=l;qr=r;v=vl;tp=tpp;
        insert(1,1,n);tp=1;
    }
    ll qry(int x,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr)return sm[x];
        sta[++top]=STA(mx[x],cm[x],nx[x],sm[x],x,tg[x]);
        int mid=l+r>>1;ll ret=0;
        if(tg[x])pushdown(x);
        if(ql<=mid)ret+=qry(ls,l,mid,ql,qr);
        if(qr>mid)ret+=qry(rs,mid+1,r,ql,qr);
        return ret;
    }
    #undef ls
    #undef rs
}xds;
signed main(){
    freopen("b.in","r",stdin);
    freopen("b.out","w",stdout);
    // cerr<<(sizeof(xds)>>20)<<endl;
    n=read();m=read();qq=read();
    sq=m/sqrt(qq);
    fo(i,1,n)a[i]=read();
    fo(i,1,m)bl[i]=(i-1)/sq+1;
    fo(i,1,m){cz[i].l=read();cz[i].r=read();cz[i].x=read();}
    fo(i,1,qq){
        q[i].l1=read();q[i].r1=read();
        q[i].l2=read();q[i].r2=read();
        q[i].id=i;
    }
    sort(q+1,q+qq+1,comQ);
    int l=1,r=0;
    fo(i,1,qq){
        if(bl[q[i].l1]!=bl[q[i-1].l1]){
            xds.build(1,1,n);xds.top=0;
            l=bl[q[i].l1]*sq+1;r=bl[q[i].l1]*sq;
        }
        if(q[i].r1<=bl[q[i].l1]*sq){
            // cerr<<xds.qry(1,1,n,q[i].l2,q[i].r2)<<endl;
            fo(j,q[i].l1,q[i].r1){
                // cerr<<j<<endl;
                xds.ins(cz[j].l,cz[j].r,cz[j].x,1);
                // cerr<<xds.qry(1,1,n,q[i].l2,q[i].r2)<<endl;
            }
            ans[q[i].id]=xds.qry(1,1,n,q[i].l2,q[i].r2);
            xds.rebuild();
            continue;
        }
        // cerr<<"SB"<<endl;
        while(r<q[i].r1){
            ++r;
            xds.ins(cz[r].l,cz[r].r,cz[r].x,0);
        }
        while(l>q[i].l1){
            --l;
            xds.ins(cz[l].l,cz[l].r,cz[l].x,1);
        }
        ans[q[i].id]=xds.qry(1,1,n,q[i].l2,q[i].r2);
        xds.rebuild();l=bl[q[i].l1]*sq+1;
    }
    fo(i,1,qq)printf("%lld\n",ans[i]);
    return 0;
}

T3

暴力\(\mathcal{O(n^3)}\)是dp,好像挺简单的,不说了

发现挺像多项式的,于是我们把每个\(a_i\)fwt一下,这样就变成了在n个多项式中选出m个对位乘,然后相加,然后在ifwt回去就是答案了

发现fwt之后的每个多项式的每一位都是1或者-1,于是我们想要找到1的数量

把桶搞出来,然后找到了1的个数,这时候权值和就可以ntt做了

AC_code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define fo(i,x,y) for(int i=(x);i<=(y);i++)
#define fu(i,x,y) for(int i=(x);i>=(y);i--)
int read(){
    int s=0,t=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')t=-1;ch=getchar();}
    while(isdigit(ch)){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
    return s*t;
}
const int N=1<<20;
const int mod=998244353;
int ksm(int x,int y){
    int ret=1;
    while(y){
        if(y&1)ret=ret*x%mod;
        x=x*x%mod;y>>=1;
    }return ret;
}
int n,m,k,buc[N];
int lim,len,af[N],w[N];
void ntt(int *a,int lim){
    fo(i,0,lim-1)if(af[i]>i)swap(a[i],a[af[i]]);
    for(int t=lim>>1,d=1;d<lim;d<<=1,t>>=1)
        for(int i=0;i<lim;i+=(d<<1))
            fo(j,0,d-1){
                int tmp=w[t*j]*a[i+j+d]%mod;
                a[i+j+d]=(a[i+j]-tmp+mod)%mod;
                a[i+j]=(a[i+j]+tmp)%mod;
            }
}
void fwt(int *a,int lim,int tp){
    for(int t=lim>>1,d=1;d<lim;d<<=1,t>>=1)
        for(int i=0;i<lim;i+=(d<<1))
            fo(j,0,d-1){
                int tmp=a[i+j+d];
                a[i+j+d]=(a[i+j]-tmp+mod)*tp%mod;
                a[i+j]=(a[i+j]+tmp)*tp%mod;
            }
}
int jc[N],inv[N];
int f[N],g[N],h[N];
signed main(){
    freopen("c.in","r",stdin);
    freopen("c.out","w",stdout);
    n=read();m=read();k=read();
    fo(i,1,n)buc[read()]++;
    fwt(buc,k,1);
    jc[0]=1;fo(i,1,n)jc[i]=jc[i-1]*i%mod;
    inv[0]=1;inv[n]=ksm(jc[n],mod-2);
    fu(i,n-1,1)inv[i]=inv[i+1]*(i+1)%mod;
    int bas=(m&1)?-1:1;fo(i,0,m)f[i]=(bas*inv[i]*inv[m-i]%mod+mod)%mod,bas=-bas;
    fo(i,0,n-m)g[i]=inv[i]*inv[n-m-i]%mod;
    for(lim=1,len=0;lim<=n;lim<<=1,len++);
    // cerr<<"SB"<<endl;
    fo(i,0,lim-1)af[i]=(af[i>>1]>>1)|((i&1)<<(len-1));
    w[0]=1;w[1]=ksm(3,(mod-1)/lim);
    fo(i,2,lim-1)w[i]=w[i-1]*w[1]%mod;
    ntt(f,lim);ntt(g,lim);
    w[0]=1;w[1]=ksm(w[1],mod-2);
    fo(i,2,lim-1)w[i]=w[i-1]*w[1]%mod;
    fo(i,0,lim-1)f[i]=f[i]*g[i]%mod;
    ntt(f,lim);int iv=ksm(lim,mod-2);
    fo(i,0,min(n,lim-1))f[i]=f[i]*iv%mod*jc[i]%mod*jc[n-i]%mod;
    // cerr<<"SB"<<endl;
    // cerr<<"ZZ"<<endl;
    int iv2=ksm(2,mod-2);
    fo(i,0,k-1){
        int x=(n+buc[i])*iv2%mod;
        // cerr<<x<<" "<<f[x]<<endl;
        h[i]=f[x];
    }
    // cerr<<"SB"<<endl;
    fwt(h,k,iv2);
    fo(i,0,k-1)printf("%lld ",h[i]);
}
posted @ 2022-05-02 21:00  fengwu2005  阅读(49)  评论(0编辑  收藏  举报