zoukankan      html  css  js  c++  java
  • 【NOIp模拟2019】题解

    T1:

    水题

    强制选根的连通块dpdp

    转到dfsdfs序上转移就只有第一个儿子和出去点,儿子之间相互连一下转移
    就变到序列上了,转移也只有O(n)O(n)

    复杂度O(nk)O(nk)

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ob==ib)?EOF:*ib++;
    }
    #define gc getchar
    inline int read(){
    	char ch=gc();
    	int res=0,f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    #define ll long long	
    #define re register
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    #define cs const
    #define poly vector<int>
    #define bg begin
    const int mod=998244353,G=3;
    inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
    inline void Add(int &a,int b){a=add(a,b);}
    inline int dec(int a,int b){return a>=b?a-b:a-b+mod;}
    inline void Dec(int &a,int b){a=dec(a,b);}
    inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
    inline void Mul(int &a,int b){a=mul(a,b);}
    inline int ksm(int a,int b){int res=1;for(;b;b>>=1,a=mul(a,a))(b&1)?(res=mul(res,a)):0;return res;}
    inline void chemx(int &a,int b){a<b?a=b:0;}
    inline void chemn(int &a,int b){a>b?a=b:0;}
    cs int N=5003,C=10004;
    int f[N][C];
    int adj[N],nxt[N<<1],to[N<<1],fa[N],in[N],w[N],v[N],tr2[N],dfn;
    int n,p,cnt;
    int arr[N],last[N],trans[N];
    vector<int>tr1[N];
    inline void addedge(int u,int v){
    	nxt[++cnt]=adj[u],adj[u]=cnt,to[cnt]=v;
    }
    void dfs(int u){
    	in[u]=++dfn,arr[dfn]=u;
    	for(int e=adj[u];e;e=nxt[e]){
    		int v=to[e];
    		last[u]=v,dfs(v);
    	}
    }
    void dfs2(int u){
    	int pre=0;
    	for(int e=adj[u];e;e=nxt[e]){
    		int v=to[e];
    		if(pre)trans[pre]=v;
    		else tr2[v]=u;
    		pre=v,dfs2(v);
    	}
    }
    inline void dp(int u){
    	re int iu=in[u];
    	for(re int tt=0;tt<tr1[u].size();tt++){
    		re int v=tr1[u][tt],iv=in[v];
    		for(re int i=0;i<=p;i++){
    			if(f[iv][i]!=-1)chemx(f[iu][i],f[iv][i]);
    		}
    	}
    	re int pt=tr2[u],ip=in[pt];
    	for(re int i=w[pt];i<=p;i++)
    		if(f[ip][i-w[pt]]!=-1)chemx(f[iu][i],f[ip][i-w[pt]]+v[pt]);
    }
    int main(){
    	n=read(),p=read();
    	for(int i=1;i<=n;i++){
    		w[i]=read(),fa[i]=read(),v[i]=read();
    		if(i!=1)addedge(fa[i],i);
    	}
    	dfs(1),dfs2(1);
    	trans[1]=n+1;in[n+1]=n+1,arr[n+1]=n+1;
    	for(re int i=1;i<=n;i++)trans[last[i]]=trans[i];
    	for(re int i=2;i<=n;i++)tr1[trans[i]].pb(i);
    	for(re int i=1;i<=n;i++)if(!adj[i])tr2[trans[i]]=i;
    	memset(f,-1,sizeof(f));
    	f[in[1]][0]=0;
    	for(int i=2;i<=n+1;i++){
    		dp(arr[i]);
    	}
    	int res=0;
    	for(int i=0;i<=p;i++)chemx(res,f[n+1][i]);
    	cout<<res;
    }
    

    T2:

    HDU原题

    最简单也就是最暴力的做法就是LCTLCT暴力维护删加边和虚子树信息

    然而根本调不出来

    Rush 1.5h+Rush 1.5h+后弃掉

    一个简单的做法是基于左右旋对于中序遍历只会修改2个点
    手玩一下可以发现
    用线段树暴力维护一下
    每次询问仍然是一个区间

    线段树维护即可

    线段树都不会写了我真是菜到家了

    #include<bits/stdc++.h>
    using namespace std;
    const int RLEN=1<<20|1;
    inline char gc(){
    	static char ibuf[RLEN],*ib,*ob;
    	(ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    	return (ob==ib)?EOF:*ib++;
    }
    #define gc getchar
    inline int read(){
    	char ch=gc();
    	int res=0,f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    #define ll long long	
    #define re register
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define pb push_back
    #define cs const
    #define poly vector<int>
    #define bg begin
    const int mod=1e9+7,G=3;
    inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
    inline void Add(int &a,int b){a=add(a,b);}
    inline int dec(int a,int b){return a>=b?a-b:a-b+mod;}
    inline void Dec(int &a,int b){a=dec(a,b);}
    inline int mul(int a,int b){return 1ll*a*b>=mod?1ll*a*b%mod:a*b;}
    inline void Mul(int &a,int b){a=mul(a,b);}
    inline int ksm(int a,int b){int res=1;for(;b;b>>=1,a=mul(a,a))(b&1)?(res=mul(res,a)):0;return res;}
    inline void chemx(int &a,int b){a<b?a=b:0;}
    inline void chemn(int &a,int b){a>b?a=b:0;}
    cs int N=200005;
    int in[N],out[N],pos[N],dfn,idx[N],fa[N],lc[N],rc[N];
    int n,q,val[N],s[N];
    inline void tain(int u){
    	in[u]=out[u]=pos[u];
    	if(lc[u])chemn(in[u],in[lc[u]]),chemx(out[u],out[lc[u]]);
    	if(rc[u])chemn(in[u],in[rc[u]]),chemx(out[u],out[rc[u]]);
    }
    void dfs(int u){
    	s[u]=val[u];
    	if(lc[u])dfs(lc[u]),Add(s[u],s[lc[u]]);
    	in[u]=out[u]=pos[u]=++dfn,idx[dfn]=u;
    	if(rc[u])dfs(rc[u]),Add(s[u],s[rc[u]]);
    	tain(u);
    }
    namespace Seg{
    	int tr[N<<2];
    	#define lc (u<<1)
    	#define rc ((u<<1)|1)
    	#define mid ((l+r)>>1)
    	inline void pushup(int u){
    		tr[u]=mul(tr[lc],tr[rc]);
    	}
    	inline void build(int u,int l,int r){
    		if(l==r){tr[u]=s[idx[l]];return;}
    		build(lc,l,mid),build(rc,mid+1,r);
    		pushup(u);
    	}
    	inline void insert(int u,int l,int r,int p,int k){
    		if(l==r){tr[u]=k;return;}
    		if(p<=mid)insert(lc,l,mid,p,k);
    		else insert(rc,mid+1,r,p,k);
    		pushup(u);
    	}
    	inline int query(int u,int l,int r,int st,int des){
    		if(st<=l&&r<=des)return tr[u];
    		int res=1;
    		if(st<=mid)Mul(res,query(lc,l,mid,st,des));
    		if(mid<des)Mul(res,query(rc,mid+1,r,st,des));
    		return res;
    	}
    	#undef lc 
    	#undef rc
    	#undef mid
    }
    int main(){
    	#ifdef Stargazer
    	freopen("lx.cpp","r",stdin);
    	#endif
    	n=read(),q=read();
    	for(int i=1;i<=n;i++){
    		val[i]=read(),lc[i]=read(),rc[i]=read();
    		if(lc[i])fa[lc[i]]=i;
    		if(rc[i])fa[rc[i]]=i;
    	}
    	dfn=0,dfs(1),Seg::build(1,1,n);
    	while(q--){
    		int op=read(),x=read(),y;
    		if(op==0){
    			if(!lc[x])continue;
    			y=x,x=lc[y];
    			Dec(s[y],s[x]),Add(s[y],s[rc[x]]);
    			Dec(s[x],s[rc[x]]),Add(s[x],s[y]);
    			Seg::insert(1,1,n,pos[x],s[x]);
    			Seg::insert(1,1,n,pos[y],s[y]);
    			if(y==lc[fa[y]])lc[fa[y]]=x;
    			else rc[fa[y]]=x;
    			fa[x]=fa[y],fa[y]=x,lc[y]=rc[x],fa[rc[x]]=y;
    			rc[x]=y;
    			tain(y),tain(x);
    		}
    		else if(op==1){
    			if(!rc[x])continue;
    			y=rc[x];
    			Dec(s[x],s[y]),Add(s[x],s[lc[y]]);
    			Dec(s[y],s[lc[y]]),Add(s[y],s[x]);
    			Seg::insert(1,1,n,pos[x],s[x]);
    			Seg::insert(1,1,n,pos[y],s[y]);
    			if(x==lc[fa[x]])lc[fa[x]]=y;
    			else rc[fa[x]]=y;
    			fa[y]=fa[x],fa[x]=y,rc[x]=lc[y],fa[lc[y]]=x;
    			lc[y]=x;
    			tain(x),tain(y);
    		}
    		else{
    			cout<<Seg::query(1,1,n,in[x],out[x])<<'
    ';
    		}
    	}
    }
    

    T3:

    TopCoderTopCoder原题

    发现这个走的方法x,yx,y不会互相影响
    fx[i][j]fx[i][j]表示iixx走到jj的方案
    fy[i][j]fy[i][j]类似

    走到(x,y)(x,y)可以直接由fx,fyfx,fy乘起来

    前缀和优化可以做到n3n^3

    考虑容斥掉不合法的方案
    g[i][j]g[i][j]表示走ii步不合法的,走到(j,j)(j,j)的方案数

    枚举走了几步不合法的
    二项式反演可以得到

    ans=i=0nj=0m/10fx[ni][txj10]fy[ni][tyj10](ni)(1)ig[i][j10]ans=sum_{i=0}^{n}sum_{j=0}^{m/10}fx[n-i][tx-j*10]*fy[n-i][ty-j*10]{nchoose i}(-1)^{i}g[i][j*10]

    #include<bits/stdc++.h>
    using namespace std;
    #define gc getchar
    inline int read(){
    	char ch=gc();
    	int res=0,f=1;
    	while(!isdigit(ch))f^=ch=='-',ch=gc();
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    	return f?res:-res;
    }
    #define re register
    #define pb push_back
    #define cs const
    #define pii pair<int,int>
    #define fi first
    #define se second
    #define ll long long
    cs int mod=1e4+7,G=3;
    inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
    inline void Add(int &a,int b){(a+=b)>=mod?(a-=mod):0;}
    inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
    inline void Dec(int &a,int b){(a-=b)<0?(a+=mod):0;}
    inline int mul(int a,int b){return a*b>=mod?a*b%mod:a*b;}
    inline void Mul(int &a,int b){a=mul(a,b);}
    inline int ksm(int a,int b,int res=1){
    	for(;b;b>>=1,a=mul(a,a))(b&1)&&(res=mul(res,a));return res;
    }
    inline void chemx(ll &a,ll b){a<b?a=b:0;}
    inline void chemn(int &a,int b){a>b?a=b:0;}
    int tx,ty,mx,my,n,m;
    cs int N=805;
    int fac[N<<1],ifac[N<<1],fx[N<<1][N],fy[N<<1][N],sx[N<<1][N],sy[N<<1][N],g[N<<1][N],ban[N];
    class FoxJumping{
    	public :
    	inline void init(){
    		ifac[0]=fac[0]=1;
    		for(int i=1;i<N*2;i++)fac[i]=mul(fac[i-1],i);
    		ifac[N*2-1]=ksm(fac[N*2-1],mod-2);
    		for(int i=N*2-2;i;i--)ifac[i]=mul(ifac[i+1],i+1);
    	}
    	inline int C(int n,int m){
    		if(n<m)return 0;
    		return mul(fac[n],mul(ifac[m],ifac[n-m]));
    	}
    	inline int getCount(int Tx,int Ty,int Mx,int My,int R,vector<int> bad){
    		tx=Tx,ty=Ty,mx=Mx,my=My,n=R,m=bad.size();
    		init();
    		for(int i=1;i<=m;i++)ban[i]=bad[i-1];
    		sort(ban+1,ban+m+1),m=unique(ban+1,ban+m+1)-ban-1;
    		m++;
    		fx[0][0]=1;
    		for(int i=0;i<n;i++)
    		for(int j=0;j<=tx;j++){
    			sx[i][j]=fx[i][j];
    			if(j)Add(sx[i][j],sx[i][j-1]);
    			Add(fx[i+1][j],sx[i][j]);
    			if(j>mx)Dec(fx[i+1][j],sx[i][j-mx-1]);
    		}
    		fy[0][0]=1;
    		for(int i=0;i<n;i++)
    		for(int j=0;j<=ty;j++){
    			sy[i][j]=fy[i][j];
    			if(j)Add(sy[i][j],sy[i][j-1]);
    			Add(fy[i+1][j],sy[i][j]);
    			if(j>my)Dec(fy[i+1][j],sy[i][j-my-1]);
    		}
    		g[0][0]=1;
    		for(int i=0;i<n;i++)
    		for(int j=0,lim=min(tx,ty)/10;j<=lim;j++){
    			for(int k=1;k<=m;k++)
    			if(j+ban[k]/10<=lim)Add(g[i+1][j+ban[k]/10],g[i][j]);
    		}
    		int res=0;
    		for(int i=0;i<=n;i++){
    			for(int j=0;j<=min(tx,ty)/10;j++){
    				int now=mul(C(n,i),mul(mul(fx[n-i][tx-j*10],fy[n-i][ty-j*10]),g[i][j]));
    				if(i&1)Dec(res,now);
    				else Add(res,now);
    			}
    		}
    		return res;
    	}
    }T;
    vector<int> s;
    int main(){
    	int tx=read(),ty=read(),mx=read(),my=read(),r=read(),k=read();
    	for(int i=1;i<=k;i++)s.pb(read());
    	cout<<T.getCount(tx,ty,mx,my,r,s);
    }
    

    总结:三道题都挺菜的

    第一题本来写的很快
    但是暴力和对拍写久了

    第二题LCTLCT写挂了,代码能力还是太差
    对性质的分析不够

    T3T3没来得及看

    暴力也都没来得及写

    代码能力也不行

    主观应该260+260+
    我还是tcltcl

  • 相关阅读:
    常用JVM配置参数
    JVM运行机制
    go 奇技淫巧
    如何实现LRU(最近最少使用)缓存淘汰算法?
    数组下标为什么是0而不是1?
    ServiceMesh 演化进程
    CAP定理详解
    vscode 调试配置信息
    Ubuntu 断网问题解决
    ubuntu 关闭指定占用端口
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/12328699.html
Copyright © 2011-2022 走看看