ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

8月2日做题日记

2022-08-02 22:00:32  阅读:147  来源: 互联网

标签:fa int top dep 做题 void 日记 Size


8.2 刷题日记

P6591 [YsOI2020]植树

换根法,处理子树大小,然后看子树大小一不一样就行。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
//#define int long long

const int Mod=1e9+7;
const int N=1e6+7,M=2e3+1;

using namespace std;

inline int read() {
	int x=0,f=0;
	char ch=getchar();
	while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
	return f?-x:x;
}

int n,Size[N];
vector<int>G[N],Ans;

void dfs1(int u,int fa){
	Size[u]=1;
	for(auto &v:G[u]){
		if(v==fa) continue;
		dfs1(v,u);Size[u]+=Size[v];
	}
}

void dfs2(int u,int fa){
	int Jg=Size[G[u][0]],flg=0;
	for(auto &v:G[u]){if(Size[v]!=Jg){flg=1;break;}}
	if(!flg) Ans.push_back(u);
	for(auto &v:G[u]){
		if(v==fa) continue;
		Size[u]-=Size[v];Size[v]+=Size[u];
		dfs2(v,u);
		Size[v]-=Size[u];Size[u]+=Size[v];
	}
}

signed main() {
	n=read();
	if(n==1) return cout<<1,0;
	for(int i=1;i<n;i++){
		int u=read(),v=read();
		G[u].push_back(v);
		G[v].push_back(u);
	}dfs1(1,0);dfs2(1,0);
	sort(Ans.begin(),Ans.end());
	for(auto &i:Ans) printf("%d ",i);
	return 0;
}

P4211 [LNOI2014]LCA

树剖,思维?为什么一离线我就不会啊。

一看式子:\(\displaystyle \sum_{i=l}^r dep_{Lca(i,z)}\),马上差分,\(\displaystyle\sum_{i=1}^{r}dep_{Lca(i,z)}- \sum_{i=1}^{l-1}dep_{Lca(i,z)}\),\(dep\) 其实就是到根的距离,那就是看每个点贡献了多少,越下的点贡献的越多,并且是累加的,直接树剖。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
//#define int long long

const int Mod=201314;
const int N=1e6+7,M=2e3+1;

using namespace std;

inline int read() {
	int x=0,f=0;
	char ch=getchar();
	while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
	return f?-x:x;
}

int n,m;
namespace Seg{
	#define lson pos<<1
	#define rson pos<<1|1
	struct Tree{int sum,lazy,len;}tree[N];

	void push_down(int pos){
		if(!tree[pos].lazy) return;
		tree[lson].lazy+=tree[pos].lazy;
		tree[rson].lazy+=tree[pos].lazy;
		tree[lson].sum+=tree[lson].len*tree[pos].lazy;
		tree[rson].sum+=tree[rson].len*tree[pos].lazy;
		tree[lson].lazy%=Mod;tree[rson].lazy%=Mod;
		tree[lson].sum%=Mod;tree[rson].sum%=Mod;
		tree[pos].lazy=0;
	}
	
	void build(int pos,int l,int r){
		tree[pos].len=r-l+1;
		if(l==r) return;int mid=l+r>>1;
		build(lson,l,mid);build(rson,mid+1,r);
	}
	
	void Modify(int pos,int l,int r,int L,int R){
//		debug
		if(l>=L&&r<=R) return tree[pos].sum+=tree[pos].len,tree[pos].lazy++,void();
		int mid=l+r>>1;push_down(pos);
		if(L<=mid) Modify(lson,l,mid,L,R);
		if(R>mid) Modify(rson,mid+1,r,L,R);
		tree[pos].sum=(tree[lson].sum+tree[rson].sum)%Mod;
	}
	
	int Query(int pos,int l,int r,int L,int R){
		if(l>=L&&r<=R) return tree[pos].sum;
		int mid=l+r>>1,res=0;push_down(pos);
		if(L<=mid) res+=Query(lson,l,mid,L,R),res%=Mod;
		if(R>mid) res+=Query(rson,mid+1,r,L,R),res%=Mod;
		return res%Mod;
	}
}

int Size[N],son[N],fath[N],dep[N],dfn[N],top[N],idx;
vector<int>G[N];
namespace Cut{
	void dfs1(int u,int fa){
		fath[u]=fa;Size[u]=1;dep[u]=dep[fa]+1;
		for(auto &v:G[u]){
			if(v==fa) continue;
			dfs1(v,u);
			Size[u]+=Size[v];
			if(Size[v]>Size[son[u]]) son[u]=v;
		}
	}
	
	void dfs2(int u,int tp){
		top[u]=tp;dfn[u]=++idx;
		if(son[u]) dfs2(son[u],tp);
		for(auto &v:G[u]){
			if(v==fath[u]||v==son[u]) continue;
			dfs2(v,v);
		}
	}
	
	void Modify(int u,int v){
		while(top[u]!=top[v]){
//			debug
			if(dep[top[v]]>dep[top[u]]) swap(u,v);
			Seg::Modify(1,1,n,dfn[top[u]],dfn[u]);
			u=fath[top[u]];
		}
		if(dep[v]<dep[u]) swap(u,v);
		Seg::Modify(1,1,n,dfn[u],dfn[v]);
	}
	
	int Query(int u,int v){
		int res=0;
		while(top[u]!=top[v]){
			if(dep[top[v]]>dep[top[u]]) swap(u,v);
			res+=Seg::Query(1,1,n,dfn[top[u]],dfn[u]);
			u=fath[top[u]];res%=Mod;
		}
		if(dep[v]<dep[u]) swap(u,v);
		res+=Seg::Query(1,1,n,dfn[u],dfn[v]);
		return res%Mod;
	}
}

struct node{int pre,z,bh;bool type;};
node A[N];int sc;

bool cmp(node a,node b){return a.pre<b.pre;}

int res1[N],res2[N];

signed main() {
	n=read(),m=read();
	for(int i=2;i<=n;i++){
		int fa=read()+1;
		G[fa].push_back(i);
		G[i].push_back(fa);
	}
	Cut::dfs1(1,0),Cut::dfs2(1,1);Seg::build(1,1,n);
	for(int i=1;i<=m;i++){
		int l=read()+1,r=read()+1,z=read()+1;
		A[++sc]=(node){l-1,z,i,0};
		A[++sc]=(node){r,z,i,1};
	}
	sort(A+1,A+sc+1,cmp);
//	for(int i=1;i<=sc;i++) cout<<A[i].bh<<" ";
	for(int i=1,pos=0;i<=sc;i++){
		while(pos<A[i].pre)++pos,Cut::Modify(1,pos);
		(A[i].type?res1[A[i].bh]:res2[A[i].bh])=Cut::Query(1,A[i].z);
	}
	for(int i=1;i<=m;i++) printf("%d\n",(res1[i]-res2[i]+Mod)%Mod);
	return 0;
}

树剖忘记处理 dep 数组导致调了两个小时,警钟敲烂。

P2606 [ZJOI2010]排列计数

组合数问题。

看这个式子,其实就是一棵树,然后还要小根堆,那么就是说根节点占一个,然后剩下的 \(i-1\) 个节点再选出 \(l\) 个来当左子树,剩下的当右子树,即:\(f[i]=C_{i-1}^{l} \times f[l] \times f[r]\),然后处理一下组合数,Lucas 一搞就行了。

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define debug cout<<"Szt ak ioi\n";
#define int long long

int Mod;
const int N=4e6+7,M=2e3+1;

using namespace std;

inline int read() {
	int x=0,f=0;
	char ch=getchar();
	while(!isdigit(ch))f|=(ch=='-'),ch=getchar();
	while(isdigit(ch))x=(x<<1)+(x<<3)+(ch&15),ch=getchar();
	return f?-x:x;
}

int n,fac[N],Size[N],f[N],inv[N];

int Pow(int a,int b){
	int res=1;a%=Mod;
	while(b){
		if(b&1) res=(res*a)%Mod;
		b>>=1;a=(a*a)%Mod;
	}
	return res;
}

void Fac(){
	fac[0]=1,inv[1]=1;
	for(int i=1;i<=n;i++) f[i<<1]=f[i<<1|1]=Size[i]=1,fac[i]=(fac[i-1]*i)%Mod;
	for(int i=n;i>=2;i--) Size[i>>1]+=Size[i];
}

int C(int a,int b){
	if(a<b) return 0;
	return fac[a]*Pow(fac[b],Mod-2)%Mod*Pow(fac[a-b],Mod-2)%Mod;
}

int Lucas(int x,int y){
	if(!y) return 1;
	return C(x%Mod,y%Mod)*Lucas(x/Mod,y/Mod)%Mod;
}

signed main() {
	n=read(),Mod=read();Fac();
	for(int i=n;i>=1;i--) f[i]=Lucas(Size[i]-1,Size[i<<1])*f[i<<1]%Mod*f[i<<1|1]%Mod;
	printf("%lld\n",f[1]);
	return 0;
}

话说这一天做仨题也是……主要是湾湾那边搞事太大了,精力不是很集中吧。

明天再接再厉。

标签:fa,int,top,dep,做题,void,日记,Size
来源: https://www.cnblogs.com/BlackDan/p/16545339.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有