省选模拟38
出题人非常良心,第二题非常的签到!
好像第一题是原题,于是我没有切掉,一直在想如何\(\mathcal{O(1)}\)转移到下一个位置
第三题是个毒瘤数据结构。。。。
T1 异或矩阵
发现我们可以对k-1二进制拆分,每次转移\(2^n\)层,这样就可以实现每次\(\mathcal{O(1)}\)转移..
AC_code
#include<bits/stdc++.h>
using namespace std;
#define int unsigned int
#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<<23;
int n,k,a[N],ans[N],res;
signed main(){
freopen("matrix.in","r",stdin);
freopen("matrix.out","w",stdout);
n=read();k=read();a[1]=read();
fo(i,2,n)a[i]=a[i-1]*1145141u+1919u*i+810u;
fo(j,0,21)if((k-1>>j)&1){
fo(i,1,n)a[i]=a[i]^a[i+(1<<j)];
}
fo(i,1,n-k+1)res=(res+(a[i]^i)*i);
printf("%u",res);
return 0;
}
T2 树
签到,直接容斥就行
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=1e5+5;
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,ans[N];
struct E{int to,nxt;}e[N*2];
int head[N],rp;
void add_edg(int x,int y){e[++rp].to=y;e[rp].nxt=head[x];head[x]=rp;}
int siz[N];
void dfs(int x,int f){
siz[x]=1;
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==f)continue;
dfs(y,x);siz[x]+=siz[y];
ans[x]=(ans[x]-ksm(2,siz[y])+1+mod)%mod;
}
ans[x]=(ans[x]+ksm(2,siz[x])-1+mod)%mod;
}
signed main(){
freopen("tree.in","r",stdin);
freopen("tree.out","w",stdout);
n=read();
fo(i,1,n-1){
int x=read(),y=read();
add_edg(x,y);
add_edg(y,x);
}
dfs(1,0);
fo(i,1,n)printf("%lld\n",ans[i]);
return 0;
}
T3 黑白树
看完题解依旧不会,听完讲评的一句话恍然大悟!
我们最难处理的是联通块修改,思考一下,我们其实可以在这个联通块的顶点加上,在边界上的异色点消除贡献
于是想要判断是不是不同色,可以根据这个点上面有几个异色的点。。。
简单来说,我们用两颗线段树来维护答案,一颗维护所有白色联通块,我们以这个为例来说
我们判断两个点是不是在同一个联通块中可以根据每个点到根的路径上的黑点个数来判断
所以我直接使用树状数组维护这个东西
那么我们pushdown的时候一旦不在同一个联通块中,就不能标记下放了(这里说的是联通块加)
我们再维护一个全加的标记,也就是处理链加和子树加的标记,这个东西不受在不在同一个联通块的影响
pushup同理,如果在一个联通块才pushup
那么我们还有一个改颜色的操作没有搞定
其实改颜色的时候直接在树状数组上修改就好了,但是发现此时这个点的子树里如果有点和子树外的点构成了一个区间,就芭比Q了
所以我们要区间覆盖一下,让所有分散的区间重新pushup一遍,实现就是代码里的liu_da
9K代码!!!
AC_code
#include<bits/stdc++.h>
using namespace std;
#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=2e5+5;
int n,m;
struct E{int to,nxt;}e[N*2];
int head[N],rp;
void add_edg(int x,int y){e[++rp].to=y;e[rp].nxt=head[x];head[x]=rp;}
int val[N],col[N];
int siz[N],son[N],top[N],dep[N];
int fa[N][20];
int dfn[N],dfm[N],idf[N],cnt;
void dfs_fi(int x,int f){
dep[x]=dep[f]+1;fa[x][0]=f;
fo(i,1,19)fa[x][i]=fa[fa[x][i-1]][i-1];
siz[x]=1;son[x]=0;
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==f)continue;
dfs_fi(y,x);siz[x]+=siz[y];
if(!son[x]||siz[y]>siz[son[x]])son[x]=y;
}
}
void dfs_se(int x,int f){
top[x]=f;dfn[x]=++cnt;idf[cnt]=x;
if(son[x])dfs_se(son[x],f);
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].to;
if(y==fa[x][0]||y==son[x])continue;
dfs_se(y,y);
}dfm[x]=cnt;
}
int LCA(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
x=fa[top[x]][0];
}return dep[x]<dep[y]?x:y;
}
int ts;
struct XDS{
struct BIT{
int tr[N];
void insert(int x,int v){
for(int i=x;i<=n;i+=(i&-i))tr[i]+=v;
}
void ins(int l,int r,int v){
insert(l,v);insert(r+1,-v);
}
int qry(int x){
int ret=0;
for(int i=x;i;i-=(i&-i))ret+=tr[i];
return ret;
}
}bit;
#define ls x<<1
#define rs x<<1|1
int mx[N*4],vs[N*4],tg[N*4],tj[N*4];
void pushup(int x,int l,int r){
int mid=l+r>>1;
int ax=bit.qry(dfn[LCA(idf[l],idf[r])]);
int al=bit.qry(dfn[LCA(idf[l],idf[mid])]);
int ar=bit.qry(dfn[LCA(idf[mid+1],idf[r])]);
// if(ts)cerr<<"pushup"<<" "<<x<<" "<<l<<" "<<r<<" "<<ax<<" "<<al<<" "<<ar<<endl;
mx[x]=0;
if(ax==al)mx[x]=max(mx[x],mx[ls]);
if(ax==ar)mx[x]=max(mx[x],mx[rs]);
}
void pushdown(int x,int l,int r){
int mid=l+r>>1;
int ax=bit.qry(dfn[LCA(idf[l],idf[r])]);
int al=bit.qry(dfn[LCA(idf[l],idf[mid])]);
int ar=bit.qry(dfn[LCA(idf[mid+1],idf[r])]);
if(tg[x]){
if(ax==al&&!vs[ls])mx[ls]+=tg[x],tg[ls]+=tg[x];
if(ax==ar&&!vs[rs])mx[rs]+=tg[x],tg[rs]+=tg[x];
tg[x]=0;
}
if(tj[x]){
if(!vs[ls])mx[ls]+=tj[x],tj[ls]+=tj[x];
if(!vs[rs])mx[rs]+=tj[x],tj[rs]+=tj[x];
tj[x]=0;
}
}
void liu_da(int x,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return ;
int mid=l+r>>1;if(tg[x]||tj[x])pushdown(x,l,r);
if(ql<=mid)liu_da(ls,l,mid,ql,qr);
if(qr>mid)liu_da(rs,mid+1,r,ql,qr);
pushup(x,l,r);return ;
}
void build(int x,int l,int r){
if(l==r){
mx[x]=val[idf[l]];
if(col[idf[l]]){
bit.ins(l,dfm[idf[l]],1);
mx[x]=0;vs[x]=1;
}
return ;
}
int mid=l+r>>1;
build(ls,l,mid);build(rs,mid+1,r);
pushup(x,l,r);
}
void c_cl_cp(int x,int l,int r,int pos,int v){
if(l==r){
liu_da(1,1,n,l,dfm[idf[l]]);
bit.ins(l,dfm[idf[l]],v);
liu_da(1,1,n,l,dfm[idf[l]]);
if(v>0)vs[x]=1;
else vs[x]=0;
return ;
}
int mid=l+r>>1;if(tg[x]||tj[x])pushdown(x,l,r);
if(pos<=mid)c_cl_cp(ls,l,mid,pos,v);
else c_cl_cp(rs,mid+1,r,pos,v);
pushup(x,l,r);return ;
// cerr<<"c_cl_cp"<<" "<<x<<" "<<l<<" "<<r<<" "<<pos<<" "<<v<<" "<<mx[x]<<endl;
}
void c_cl(int x,int v){c_cl_cp(1,1,n,dfn[x],v);}
void c_tuan_cp(int x,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){
int aa=bit.qry(dfn[LCA(idf[ql],idf[qr])]);
int ax=bit.qry(dfn[LCA(idf[l],idf[r])]);
if(aa==ax)mx[x]+=v,tg[x]+=v;
return ;
}
int mid=l+r>>1;if(tg[x]||tj[x])pushdown(x,l,r);
if(ql<=mid)c_tuan_cp(ls,l,mid,ql,qr,v);
if(qr>mid)c_tuan_cp(rs,mid+1,r,ql,qr,v);
pushup(x,l,r);return ;
}
void c_tuan(int x,int v,int c){
int p=x,now=bit.qry(dfn[x]);
// cerr<<now<<endl;
fu(i,19,0)if(fa[p][i]&&(col[fa[p][i]]==c)&&bit.qry(dfn[fa[p][i]])==now)p=fa[p][i];
// cerr<<p<<endl;
c_tuan_cp(1,1,n,dfn[p],dfm[p],v);
}
void c_all_cp(int x,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){
// cerr<<"c_all_cp"<<" "<<l<<" "<<r<<" "<<ql<<" "<<qr<<" "<<v<<endl;
mx[x]+=v;tj[x]+=v;
return ;
}
int mid=l+r>>1;if(tg[x]||tj[x])pushdown(x,l,r);
if(ql<=mid)c_all_cp(ls,l,mid,ql,qr,v);
if(qr>mid)c_all_cp(rs,mid+1,r,ql,qr,v);
pushup(x,l,r);return ;
}
void c_all(int l,int r,int v){c_all_cp(1,1,n,l,r,v);}
void f_vl_cp(int x,int l,int r,int pos,int v){
if(l==r)return mx[x]=v,void();
int mid=l+r>>1;if(tg[x]||tj[x])pushdown(x,l,r);
if(pos<=mid)f_vl_cp(ls,l,mid,pos,v);
else f_vl_cp(rs,mid+1,r,pos,v);
pushup(x,l,r);return ;
}
void f_vl(int x,int v){f_vl_cp(1,1,n,dfn[x],v);}
int res_vl;
void q_vl_cp(int x,int l,int r,int ql,int qr){
// cerr<<"q_vl_cp"<<" "<<l<<" "<<r<<" "<<ql<<" "<<qr<<" "<<mx[x]<<" "<<tg[x]<<" "<<tj[x]<<endl;
if(ql<=l&&r<=qr){
int aa=bit.qry(dfn[LCA(idf[ql],idf[qr])]);
int ax=bit.qry(dfn[LCA(idf[l],idf[r])]);
if(aa==ax)res_vl=max(res_vl,mx[x]);
return ;
}
int mid=l+r>>1;if(tg[x]||tj[x])pushdown(x,l,r);
if(ql<=mid)q_vl_cp(ls,l,mid,ql,qr);
if(qr>mid)q_vl_cp(rs,mid+1,r,ql,qr);
pushup(x,l,r);return ;
}
int q_vl(int x,int c){
res_vl=0;
int p=x,now=bit.qry(dfn[x]);
// cerr<<now<<endl;
fu(i,19,0)if(fa[p][i]&&(col[fa[p][i]]==c)&&bit.qry(dfn[fa[p][i]])==now)p=fa[p][i];
// cerr<<p<<endl;
q_vl_cp(1,1,n,dfn[p],dfm[p]);
return res_vl;
}
int q_vv_cp(int x,int l,int r,int pos){
if(l==r)return mx[x];
int mid=l+r>>1,ret=0;if(tg[x]||tj[x])pushdown(x,l,r);
if(pos<=mid)ret=q_vv_cp(ls,l,mid,pos);
else ret=q_vv_cp(rs,mid+1,r,pos);
pushup(x,l,r);return ret;
}
int q_vv(int x){return q_vv_cp(1,1,n,dfn[x]);}
#undef ls
#undef rs
}xds0,xds1;
void c_chin(int x,int y,int v){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]])swap(x,y);
xds0.c_all(dfn[top[x]],dfn[x],v);
xds1.c_all(dfn[top[x]],dfn[x],v);
x=fa[top[x]][0];
}
if(dep[x]>dep[y])swap(x,y);
// cerr<<x<<" "<<y<<endl;
xds0.c_all(dfn[x],dfn[y],v);
xds1.c_all(dfn[x],dfn[y],v);
// cerr<<xds0.q_vv(3)<<" "<<xds1.q_vv(3)<<endl;
}
void c_subt(int x,int v){
xds0.c_all(dfn[x],dfm[x],v);
xds1.c_all(dfn[x],dfm[x],v);
}
void c_tuan(int x,int v){
// cerr<<x<<" "<<col[x]<<endl;
if(!col[x])xds0.c_tuan(x,v,col[x]);
else xds1.c_tuan(x,v,col[x]);
}
void c_cl(int x){
if(!col[x]){
int v=xds0.q_vv(x);xds1.f_vl(x,v);xds0.f_vl(x,0);
xds0.c_cl(x,1);xds1.c_cl(x,-1);
col[x]=1;
}
else {
int v=xds1.q_vv(x);xds0.f_vl(x,v);xds1.f_vl(x,0);
xds0.c_cl(x,-1);xds1.c_cl(x,1);
col[x]=0;
}
}
int q_vl(int x){
if(!col[x])return xds0.q_vl(x,col[x]);
else return xds1.q_vl(x,col[x]);
}
signed main(){
freopen("astill.in","r",stdin);
freopen("astill.out","w",stdout);
n=read();m=read();
fo(i,1,n-1){
int x=read(),y=read();
add_edg(x,y);add_edg(y,x);
}
dfs_fi(1,0);dfs_se(1,1);
fo(i,1,n)col[i]=read();
fo(i,1,n)val[i]=read();
xds0.build(1,1,n);
fo(i,1,n)col[i]^=1;
xds1.build(1,1,n);
fo(i,1,n)col[i]^=1;
while(m--){
int tp=read(),x=0,y=0,v=0;
if(tp==1){
ts=1;
x=read();c_cl(x);
}
if(tp==2){
x=read();v=read();
c_tuan(x,v);
}
if(tp==3){
x=read();
printf("%d\n",q_vl(x));
}
if(tp==4){
x=read();y=read();v=read();
c_chin(x,y,v);
}
if(tp==5){
x=read();v=read();
c_subt(x,v);
}
// fo(i,1,n){
// if(!col[i])cerr<<xds0.q_vv(i)<<" ";
// else cerr<<xds1.q_vv(i)<<" ";
// }cerr<<endl;
}
}
QQ:2953174821