专栏文章

【0】做题心得 - 2025 NOIP #66 - T1【计数】【点边容斥】

题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@min3o4dg
此快照首次捕获于
2025/12/01 20:02
3 个月前
此快照最后确认于
2025/12/01 20:02
3 个月前
查看原文
打得最好的一集,这题秒切。你发现有点边容斥连通块个数为点数减去边数。然后我们随便搜索一次给每一个点定义一个父亲,你发现当一个点与父亲都被选中时可以直接把贡献扔到父亲上,自己就没用贡献。所以考虑一个点被包括的所有矩阵,然后减去与父亲同在的矩阵,计算是容易的。
CPP
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+10;
const ll P=1e9+7;
int n;
ll lx,rx,ly,ry,x[N],y[N];
int fat[N];
ll ans;
vector<int>e[N];
void dfs(int p,int fa){
	fat[p]=fa;
	for(auto v:e[p])if(v^fa)
		dfs(v,p);
	return;
}
int main(){
	freopen("build.in","r",stdin);
	freopen("build.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>lx>>rx>>ly>>ry;
	for(int i=1;i<=n;i++)
		cin>>x[i]>>y[i];
	for(int i=1;i<n;i++){
		int u,v;
		cin>>u>>v;
		e[u].push_back(v);
		e[v].push_back(u);
	}
	dfs(1,0);
	x[0]=-1,y[0]=-1;
	for(int i=1;i<=n;i++){
		ll posx=x[i],posy=y[i];
		ll fatx=x[fat[i]],faty=y[fat[i]];
		ans+=(posx-lx+1ll)%P*(rx-posx+1ll)%P*(posy-ly+1ll)%P*(ry-posy+1ll)%P;
		ans%=P;
		if(fatx!=-1){
			ll elx=min(posx,fatx), ely=min(posy,faty),
			   erx=max(posx,fatx), ery=max(posy,faty);
			ans-=(elx-lx+1ll)%P*(rx-erx+1ll)%P*(ely-ly+1ll)%P*(ry-ery+1ll)%P;
			ans=(ans+P)%P;
		}
	}
	cout<<ans;
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...