zoukankan      html  css  js  c++  java
  • 【loj3044】【zjoi2019】Minimax

    题目

    描述

    ​ 给出一颗树,定义根节点1的深度为1,其他点深度为父亲深度+1;

    ​ 如下定义一个点的点权:
    ​ 1.叶子:为其编号;2.奇数深度:为其儿子编号最大值;3.偶数深度:为其儿子编号最小值;

    ​ 对于一个叶子集合 (S) ,你可以修改 $w_i o w_i pm C ,i in S $ , 称使得根权值改变的最小(C)(S)的稳定度;(如果无论如何根都不变规定稳定度为(n)

    ​ 询问稳定度为 (i in [L,R]) 的有多少个,对每个 (i) 依次输出;

    范围

    ​ $2 le n le 2 imes 10^5 , 1 le L le R le n $

    题解

    • 由于点权互不相同,所以一定可以找到一条到某个叶子的链:链上的值都是根节点的值,记这个链为(key) ,并且顶点的权值改变的充要条件是(key)上某个点改变。考虑统计不改变的情况,对(key)上每个点分奇偶做一个 (dp) 再相乘,可以求出不变方案数,获得了一个 (O(n(R-L))) 的算法。

    • 从小到大考虑 (C) ,每个叶子的初始值只会改变一次,用(ddp)维护即可。注意由于系数有0需要特判一下;

      #include<bits/stdc++.h>
      #define mod 998244353
      #define ll long long 
      #define ls (k<<1)
      #define rs (k<<1|1)
      #define mk make_pair
      #define pir pair<int,int>
      #define fi first
      #define se second  
      #define il inline 
      #define rg register 
      using namespace std;
      const int N=200010;
      int n,L,R,o=1,hd[N],d[N],f[N],g[N],col[N],dep[N],lf[N],id[N];
      int fa[N],sz[N],sn[N],st[N],tp[N],dn[N],idx,now,ans[N],cnt,tot;
      struct Edge{int v,nt;}E[N<<1];
      struct data{
      	int a,b;
      	il data operator +(const data&A)const{
      		data ret;
      		ret.a=(ll)a*A.a%mod;
      		ret.b=((ll)A.b*a%mod+b)%mod;
      		return ret;
      	}//维护ax+b的迭代;
      }tr[N<<2];
      il int pw(int x,int y){
      	int re=1;x%=mod;
      	while(y){
      		if(y&1)re=(ll)re*x%mod;
      		y>>=1;x=(ll)x*x%mod;
      	}
      	return re;
      } 
      pir a[N];int b[N];
      il int val(pir A){return A.se?0:A.fi;}
      il pir operator +(pir A,int B){if(!B)A.se++;else A.fi=(ll)A.fi*B%mod;return A;}
      il pir operator -(pir A,int B){if(!B)A.se--;else A.fi=(ll)A.fi*pw(B,mod-2)%mod;return A;}
      //用来处理ax+b系数a为0的情况;
      il char gc(){
      	static char*p1,*p2,s[1000000];
      	if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
      	return(p1==p2)?EOF:*p1++;
      }
      il int rd(){
      	int x=0;char c=gc();
      	while(c<'0'||c>'9')c=gc();
      	while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc();
      	return x;
      }
      il void adde(int u,int v){
      	d[u]++,d[v]++; 
      	E[o]=(Edge){v,hd[u]};hd[u]=o++;
      	E[o]=(Edge){u,hd[v]};hd[v]=o++;
      }
      il void Min(int&x,int y){if(x>y)x=y;}
      il void Max(int&x,int y){if(x<y)x=y;}
      void dfs_pre(int u,int F){
      	dep[u]=dep[fa[u]=F]+1;sz[u]=1;
      	if(u!=1&&d[u]==1){lf[u]=2;f[u]=dn[u]=u;return;}
      	lf[u]=1;f[u]=dep[u]&1?0:n;
      	for(rg int i=hd[u];i;i=E[i].nt){
      		int v=E[i].v;
      		if(v==F)continue;
      		dfs_pre(v,u);
      		sz[u]+=sz[v];lf[u]=(ll)lf[u]*lf[v]%mod;
      		if(sz[sn[u]]<sz[v])sn[u]=v,dn[u]=dn[v];
      		if(dep[u]&1)Max(f[u],f[v]);else Min(f[u],f[v]);
      	}
      }
      //以下为朴素dp部分:
      //***************************************
      void dfs_mn(int u,int T){
      	st[++idx]=u;id[u]=idx;
      	tp[u]=T;g[u]=1;col[u]=1;
      	if(u!=1&&d[u]==1){a[u]=mk(0,0),b[u]=g[u]=(u<=f[1])<<1;return;}
      	if(dep[u]&1){
      		a[u]=mk(1,0);b[u]=0;
      		dfs_mn(sn[u],T);
      		g[u]=(ll)g[u]*g[sn[u]]%mod;
      		for(rg int i=hd[u];i;i=E[i].nt){
      			int v=E[i].v;
      			if(v==fa[u]||v==sn[u])continue;
      			dfs_mn(v,v);
      			g[u]=(ll)g[u]*g[v]%mod;
      			a[u]=a[u]+g[v]%mod;
      		}
      	}else{
      		a[u]=mk(1,0);
      		dfs_mn(sn[u],T);
      		g[u]=(ll)g[u]*(lf[sn[u]]-g[sn[u]]+mod)%mod;
      		for(rg int i=hd[u];i;i=E[i].nt){
      			int v=E[i].v;
      			if(v==fa[u]||v==sn[u])continue;
      			dfs_mn(v,v);
      			g[u]=(ll)g[u]*(lf[v]-g[v]+mod)%mod;
      			a[u]=a[u]+((lf[v]-g[v]+mod)%mod);
      		}
      		g[u]=(lf[u]-g[u]+mod)%mod;
      		b[u]=(lf[u]-(ll)val(a[u])*lf[sn[u]]%mod+mod)%mod;
      	}
      }
      void dfs_mx(int u,int T){
      	st[++idx]=u;id[u]=idx;
      	tp[u]=T;g[u]=1;col[u]=2;
      	if(u!=1&&d[u]==1){a[u]=mk(0,0),b[u]=g[u]=(u>=f[1])<<1;return;}
      	if(dep[u]&1){
      		a[u]=mk(1,0);
      		dfs_mx(sn[u],T);
      		g[u]=(ll)g[u]*(lf[sn[u]]-g[sn[u]]+mod)%mod;
      		for(rg int i=hd[u];i;i=E[i].nt){
      			int v=E[i].v;
      			if(v==fa[u]||v==sn[u])continue;
      			dfs_mx(v,v);
      			g[u]=(ll)g[u]*(lf[v]-g[v]+mod)%mod;
      			a[u]=a[u]+(lf[v]-g[v]+mod)%mod;
      		}
      		g[u]=(lf[u]-g[u]+mod)%mod;
      		b[u]=(lf[u]-(ll)val(a[u])*lf[sn[u]]%mod+mod)%mod;
      	}else{
      		a[u]=mk(1,0);b[u]=0;
      		dfs_mx(sn[u],T);
      		g[u]=(ll)g[u]*g[sn[u]]%mod;
      		for(rg int i=hd[u];i;i=E[i].nt){
      			int v=E[i].v;
      			if(v==fa[u]||v==sn[u])continue;
      			dfs_mx(v,v);
      			g[u]=(ll)g[u]*g[v]%mod;
      			a[u]=a[u]+g[v]%mod;
      		}
      	}
      }
      void dfs_key(int u){
      	for(rg int i=hd[u];i;i=E[i].nt){
      		int v=E[i].v;
      		if(v==fa[u])continue;
      		if(f[u]==f[v]){dfs_key(v);continue;}
      		if(dep[u]&1)dfs_mn(v,v);else dfs_mx(v,v);
      		now=(ll)now*g[v]%mod;
      	}
      }
      //******************************************
      il void pushup(int k){tr[k]=tr[ls]+tr[rs];}
      void build(int k,int l,int r){
      	if(l==r){tr[k]=(data){val(a[st[l]]),b[st[l]]};return;}
      	int mid=l+r>>1;
      	build(ls,l,mid);
      	build(rs,mid+1,r);
      	pushup(k);
      }
      void update(int k,int l,int r,int x){
      	/*{
      		cnt++;
      	}*/
      	if(l==r){tr[k]=(data){val(a[st[l]]),b[st[l]]};return;}
      	int mid=l+r>>1;
      	if(x<=mid)update(ls,l,mid,x);
      	else update(rs,mid+1,r,x);
      	pushup(k);
      }
      data query(int k,int l,int r,int x,int y){
      	/*{
      		cnt++;
      	}*/
      	if(l==x&&r==y)return tr[k];
      	int mid=l+r>>1;
      	if(y<=mid)return query(ls,l,mid,x,y);
      	else if(x>mid)return query(rs,mid+1,r,x,y);
      	else return query(ls,l,mid,x,mid)+query(rs,mid+1,r,mid+1,y);
      }
      il void Update_mn(int u){
      	int tmp,tu,du,v;
      	a[u]=mk(0,0),b[u]=1;
      	while(1){
      		tot++;
      		tu=tp[u];du=dn[u];
      		update(1,1,n,id[u]);
      		tmp=g[tu],g[tu]=query(1,1,n,id[tu],id[du]).b;
      		v=tu,u=fa[tu];
      		if(!col[u])break;
      		if(dep[u]&1){
      			a[u]=a[u]-tmp+g[v];
      			b[u]=0;
      		}else {
      			a[u]=a[u]-(lf[v]-tmp+mod)%mod+(lf[v]-g[v]+mod)%mod;
      			b[u]=(lf[u]-(ll)lf[sn[u]]*val(a[u])%mod+mod)%mod;
      		}
      	}
      	now=(ll)now*pw(tmp,mod-2)%mod*g[v]%mod;
      }
      il void Update_mx(int u){
      	int tmp,tu,du,v;
      	a[u]=mk(0,0),b[u]=1;
      	while(1){
      		tot++;
      		tu=tp[u];du=dn[u];
      		update(1,1,n,id[u]);
      		tmp=g[tu],g[tu]=query(1,1,n,id[tu],id[du]).b;
      		v=tu,u=fa[tu];
      		if(!col[u])break;
      		if(dep[u]&1){
      			a[u]=a[u]-(lf[v]-tmp+mod)%mod+(lf[v]-g[v]+mod)%mod;
      			b[u]=(lf[u]-(ll)lf[sn[u]]*val(a[u])%mod+mod)%mod;
      		}else{
      			a[u]=a[u]-tmp+g[v];
      			b[u]=0;
      		}
      	}
      	now=(ll)now*pw(tmp,mod-2)%mod*g[v]%mod;
      }
      char ps[1000000],*pp=ps;
      void push(char x){
      	if(pp==ps+1000000)fwrite(ps,1,1000000,stdout),pp=ps;
      	*pp++=x;
      }
      void write(int x){
      	if(!x){push('0');push(' ');return;}
      	static int sta[20],top;
      	while(x)sta[++top]=x%10,x/=10;
      	while(top)push(sta[top--]^'0');
      	push(' ');
      }
      void flush(){fwrite(ps,1,pp-ps,stdout);}
      int main(){
      	//freopen("minimax.in","r",stdin);
      	//freopen("minimax.out","w",stdout);
      	n=rd();L=rd();R=rd();
      	for(rg int i=1;i<n;++i)adde(rd(),rd());
      	dfs_pre(1,0);
      	now=1;dfs_key(1);
      	ans[1]=(lf[1]-now+mod)%mod;
      	build(1,1,n);
      	//cerr<<fixed<<setprecision(2)<<1.0*clock()/CLOCKS_PER_SEC<<endl;
      	for(rg int i=2,j1=f[1]-1,j2=f[1]+1;i<n;++i){
      		while(j1>=1&&j1+i>f[1]){if(d[j1]==1&&col[j1]==1)Update_mn(j1);j1--;}
      		while(j2<=n&&j2-i<f[1]){if(d[j2]==1&&col[j2]==2)Update_mx(j2);j2++;}
      		ans[i]=(lf[1]-now+mod)%mod;
      		/*if(i==1000){
      			write(cnt);
      			write(tot);
      			break;
      		}*/
      	//	cerr<<fixed<<setprecision(2)<<1.0*clock()/CLOCKS_PER_SEC<<endl;
      	}
      	ans[n]=lf[1]-1;
      	for(rg int i=n;i;--i)ans[i]=(ans[i]-ans[i-1]+mod)%mod;
      	for(rg int i=L;i<=R;++i)write(ans[i]);//printf("%d ",ans[i]);
      	flush();
      	//printf("%.2lf
      ",1.0*clock()/CLOCKS_PER_SEC);
      	//cerr<<fixed<<setprecision(2)<<1.0*clock()/CLOCKS_PER_SEC<<endl;
      	return 0;
      }
      
  • 相关阅读:
    函数式编程
    _.pick lodash
    Vue mixins extend
    js 导入json配置文件
    FormData
    shell中的调试与计算
    linux命令(6/10):find 命令
    Linux性能测试分析命令_sar+iostat+vmstat+top
    linux命令详解之(at)
    linux命令(6/9):watch命令
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10681056.html
Copyright © 2011-2022 走看看