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]);
}
QQ:2953174821