CF题解

D. Training Session 1700

https://codeforces.com/contest/1598/problem/D
题解:由于正面条件少不好做,我们考虑反面,其能给我们提供相当多的性质。即:3题中,至少有两题难度相同,至少有两题主题一致。而没有两题一摸一样,故假定有3题x,y,z,则x和y难度相同,x和z难度相同。现在问题变得非常好做了,我们只需预处理难度一致的题,和主题一致的题数量,接着枚举i,每次ans+同主题题数*同难度题数,最后取反即可。

#include<bits/stdc++.h>
#define int long long
#define pb push_back
using namespace std;
const int N=2e5+100;
int a[N],b[N],p[N],f[N][4],res=0;
pair<int,int> c[N];
int v[N],vv[N];

void solve(){
	int n,ans=0,t=0;cin>>n;
	res=0;
	for(int i=1;i<=n;i++){
		cin>>a[i]>>b[i];
		v[a[i]]++;
		vv[b[i]]++;	
	}
	ans=n*(n-1)*(n-2)/6;
	for(int i=1;i<=n;i++){
		ans-=(v[a[i]]-1)*(vv[b[i]]-1);
	}
	cout<<ans<<endl;
	for(int i=1;i<=n;i++) v[i]=vv[i]=0;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
	int T;cin>>T;
	while(T--)
	solve();
}

E. Staircases 2100 dp

https://codeforces.com/contest/1598/problem/E
题解:我们可以处理出没经过任何操作时候的所有阶梯数,令f(i,j,0/1)表示到(i,j)的且此步为下或右数量,则对x,y求和即可得阶梯数,f(i,j,0)=f(i,j-1,1)+1,f(i,j,1)同理。
我们考虑如何处理操作:我们发现每步操作其实只会影O(n)个格子的数量,故我们可以每步更新f(i,j,0/1),受到影响的格子是有阶梯经过(x,y)的所有格子。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1005;
	int ans=0;
	int n,m,Q;
int f[N][N][3],g[N][N][3],v[N][N],vis[N][N],s[N][N];
queue<pair<int,int> >q;
signed main(){
	cin>>n>>m>>Q;

	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			f[i][j][1]=f[i-1][j][2]+1;
			f[i][j][2]=f[i][j-1][1]+1;
			if(i==1) f[i][j][1]=0;
			if(j==1) f[i][j][2]=0;
			ans+=f[i][j][1]+f[i][j][2]+1;
			s[i][j]=f[i][j][1]+f[i][j][2]+1;
		}
	}
	for(int i=1;i<=Q;i++){
		int x,y;cin>>x>>y;
		if(!v[x][y]){
			v[x][y]=1;
			int w=f[x][y][1]+f[x][y][2]+1;
			ans-=w;
			vis[x][y]=i;f[x][y][1]=-1,f[x][y][2]=-1;
			q.push({x+1,y});q.push({x,y+1});
			for(int j=x+1,k=y+1;j<=n&&k<=m;j++,k++){
				q.push({j,k});q.push({j+1,k});q.push({j,k+1});
			}
			while(q.size()){
				auto [x,y]=q.front();q.pop();
				if(x>n||y>m) continue;
				if(f[x][y][1]==-1) continue;
				int w=f[x][y][1]+f[x][y][2]+1;
				f[x][y][1]=f[x-1][y][2]+1;
				f[x][y][2]=f[x][y-1][1]+1;
				if(x==1) f[x][y][1]=0;
				if(y==1) f[x][y][2]=0;
				w=w-f[x][y][1]-f[x][y][2]-1;
				ans-=w;
			}
		}
		else{
			v[x][y]=0;
			f[x][y][1]=f[x-1][y][2]+1;
			f[x][y][2]=f[x][y-1][1]+1;
			if(x==1) f[x][y][1]=0;
			if(y==1) f[x][y][2]=0;
			ans+=f[x][y][1]+f[x][y][2]+1;
				q.push({x+1,y});q.push({x,y+1});
			for(int j=x+1,k=y+1;j<=n&&k<=m;j++,k++){
				q.push({j,k});q.push({j+1,k});q.push({j,k+1});
			}
			while(q.size()){
				auto [x,y]=q.front();q.pop();
				if(x>n||y>m) continue;
				int w=f[x][y][1]+f[x][y][2]+1;
				if(f[x][y][1]==-1) continue;
				f[x][y][1]=f[x-1][y][2]+1;
				f[x][y][2]=f[x][y-1][1]+1;
				if(x==1) f[x][y][1]=0;
				if(y==1) f[x][y][2]=0;
				w=w-f[x][y][1]-f[x][y][2]-1;
				ans-=w;
			}
		}
		cout<<ans<<endl;
	}
}

D. Treelabeling 2100 构造 gq

https://codeforces.com/contest/1605/problem/D
题解:不好入手,我们西先考虑怎么样能够赢得最多,显然是每个点都是孤立点,那么每个点都可走。这样是可行的吗?我们又发现由于是树,我们可以分层的odd/even考虑,由抽屉原理,其中必有一个是<=n/2,而两点不可互通的条件是二进制最高位不同,而最高位相同的数的个数为2的幂次,故我们总可以用几类(二进制最高位数为k的数有f(k)个)f(k)组成较小那个层数,即保证层与层不互通。故得到最优构造。

#include<bits/stdc++.h>
#define int long long
#define pb push_back
using namespace std;
const int N=2e5+10;
int m;
int a[N],d[N],c[2],vis[N];
queue<int> q,qq;
vector<int> g[N];
void dfs(int x,int fa){
	d[x]=d[fa]^1;
	c[d[x]]++;
	for(auto it:g[x]){
		if(it==fa) continue;
		dfs(it,x);
	}
}
void dfss(int x,int fa){
	if(d[x]==m){
		a[x]=q.front();q.pop();
	}
	else{
		a[x]=qq.front();qq.pop();
	}
	for(auto it:g[x]){
		if(it==fa) continue;
		dfss(it,x);
	}
}
void solve(){
	while(q.size()) q.pop();
	while(qq.size()) qq.pop();
	c[0]=c[1]=0;
	int n;cin>>n;
	for(int i=1;i<=n;i++) g[i].clear(),vis[i]=0;
	for(int i=1;i<n;i++){
		int u,v;cin>>u>>v;
		g[u].pb(v);g[v].pb(u);
	}
	if(n==1){
		cout<<1<<endl;return;
	}
	dfs(1,0);
	if(c[0]<c[1]) m=0;
	else m=1;
	int w=c[m],cnt=0;
	while(w){
		if(w%2){
			for(int i=(1<<cnt);i<(1<<(cnt+1));i++)
			q.push(i),vis[i]=1;
		}
		w/=2;
		cnt++;
	}
	for(int i=1;i<=n;i++){
		if(!vis[i]) qq.push(i);
	}
	dfss(1,0);
	for(int i=1;i<=n;i++){
		cout<<a[i]<<" ";
	}
	cout<<endl;
}
signed main(){
	int T;
	cin>>T;
	while(T--) solve();
}
posted @ 2023-04-25 21:41  wrong,anser  阅读(12)  评论(0)    收藏  举报