返回顶部

CSP22

题面

T1放了个啥?
T1读假了好几遍
首先一行不能为空,一列的空位必须相邻,一列可以为空

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N =2e2+5,mod=998244353;
int n,m;ll g[N][N],jie[N],inv[N];
ll qpow(ll a, ll b)
{
	ll ans=1;
	while(b)
	{
		if(b&1)ans=ans*a%mod;
		b>>=1;a=a*a%mod;
	}
	return ans;
}
ll C(int n,int m)
{
	return jie[n]*inv[m]%mod*inv[n-m]%mod;
}
int vis[N];ll ans=0;
ll calc(ll i)
{
	return i*(i+1)/2;
}
map <ull,bool> mp;
void dfs(int u)
{
	// cout<<u<<endl;

	if(u==n+1)
	{
		int cnt=0;
		for(int i=1;i<=m;i++){
			cnt=0;int zero=0;
			for(int j=1;j<=n;j++)
				{
					if(g[j][i])cnt++;
					else
					{

						if(zero&&zero!=j-1)
						{
							return;
						}
						zero=j;
					}
				}
			if(cnt==n)return ;
		}
		ull zt=0;

		
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				zt=zt*10+(g[i][j]);
				// cout<<g[i][j]<<" ";
			}
			// cout<<endl;
		}
		// cout<<endl;
		ans++;
		// if(!mp[zt])ans++;
		// mp[zt]=1;
		// cout<<zt<<endl;
		return ;
	}
	for(int len=1;len<=m;len++)
		for(int i=1;i+len-1<=m;i++)
		{
			for(int k=i;k<=i+len-1;k++)g[u][k]=1;
			dfs(u+1);
			for(int k=i;k<=i+len-1;k++)g[u][k]=0;
		}
	return;
}
int main()
{
	speed();
	freopen("magic.in","r",stdin);
	freopen("magic.out","w",stdout);	
	// freopen("in.in","r",stdin);
	// freopen("out.out","w",stdout);
	cin>>n>>m;dfs(1);
	// cout<<dfs(1)<<endl;
	cout<<ans<<endl;
	return 0;
}

暴力大赛
T2暴力,大道至简

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 2e5+5;
int n,m,be[N];vector <pii> edge[N];
inline int read()
{
	int x=0,f=1;char ch=getchar_unlocked();
	for(;ch<'0'||ch>'9';ch=getchar_unlocked())if(ch=='-')f=-f;
	for(;ch>='0'&&ch<='9';ch=getchar_unlocked())x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
inline void write(int x)
{
	x==0?void(0):(write(x/10),putchar_unlocked((x%10)|48),void(0));
}
int ans=0,dis[N];
inline void dfs(int u,int fa)
{
	dis[u]=dis[fa]+1;
	ans=max(ans,dis[u]);
	for(auto [to,id]:edge[u])
	{
		if(to==fa||be[id])continue;
		dfs(to,u);
	}
}
int main()
{
	speed();
	// freopen("in.in","r",stdin);
	// freopen("out.out","w",stdout);
	freopen("block.in","r",stdin);
	freopen("block.out","w",stdout);	
	// freopen("block1.in","r",stdin);	
	// freopen("out.out","w",stdout);
	n=read();m=read();
	int u,v;
	for(int i=1;i<=n-1;i++)
	{
		u=read();v=read();
		edge[u].pb({v,i});edge[v].pb({u,i});
	}
	int op;
	for(int i=1;i<=m;i++)
	{
		op=read();
		if(op==1)
		{
			u=read();
			be[u]=1;
		}
		else if(op==2)
		{
			u=read();ans=0;
			dis[0]=-1;
			dfs(u,0);
			ans==0?(putchar_unlocked('0'),void(0)):write(ans);
			putchar_unlocked('\n');
		}
	}
	return 0;
}

T3暴力\(dp\)

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 3e3+5;
int n,m,c,k,q,sum[N][N],dp[N][N],mu[N],diff[N][N];
struct jz
{
	int x1,y1,x2,y2;
}a[N];
int lowbit(int x){return x&-x;}
void add(int x,int y,int v)
{
	for(int i=x;i;i-=lowbit(i))
	{
		for(int j=y;j;j-=lowbit(j))
		{
			sum[i][j]+=v;
		}
	}
}
int query(int x,int y)
{
	int ans=0;
	for(int i=x;i<=n;i+=lowbit(i))
	{
		for(int j=y;j<=n;j+=lowbit(j))
		{
			ans+=sum[i][j];
		}
	}	
	return ans;
}
ll solve(int x,int y)
{
	for(int i=0;i<=n;i++)
		for(int j=0;j<=x;j++)dp[i][j]=0;
	// memset(dp,0,sizeof dp);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=min(i,x);j++)
		{
			dp[i][j]=dp[i-1][j];
			ll val=0;
			for(ll k=1;k<=min(mu[i],m-mu[i])&&k<=y;k++)
			{
				val=max(val,(y-k)*k);
			}
			// cout<<val<<endl;
			dp[i][j]=max<ll>(dp[i][j],dp[i-1][j-1]+val);
		}
	}
	return dp[n][x];
}
void update(int x1,int y1,int x2,int y2)
{
	diff[x1][y1]++;
	diff[x2+1][y1]--;
	diff[x1][y2+1]--;
	diff[x2+1][y2+1]++;
}
int main()
{
	speed();
		freopen("army.in","r",stdin);
	freopen("army.out","w",stdout);
	// freopen("army1.in","r",stdin);
	// freopen("in.in","r",stdin);
	// freopen("out1.out","w",stdout);
	cin>>n>>m>>c>>k>>q;
	for(int i=1;i<=c;i++)
	{
		cin>>a[i].x1>>a[i].y1>>a[i].x2>>a[i].y2;
		update(a[i].x1,a[i].y1,a[i].x2,a[i].y2);
	}	
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+diff[i][j];
			if(sum[i][j]>=k)mu[i]++;
			// if(sum[i][j]>=k)mu[i]++;
			// cout<<sum[i][j]<<" ";
		}
		// cout<<endl;
	}
	int x,y;
	for(int i=1;i<=q;i++)
	{
		cin>>x>>y;
		cout<<solve(x,y)<<endl;
	}
	return 0;

}

除了差分,还可以预处理出来,这样就不用\(dp\)了,至多\(40\)

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 3e3+5;
int n,m,c,k,q,sum[N][N],dp[N][N],mu[N],diff[N][N];
struct jz
{
	int x1,y1,x2,y2;
}a[300005];
int lowbit(int x){return x&-x;}
void add(int x,int y,int v)
{
	for(int i=x;i;i-=lowbit(i))
	{
		for(int j=y;j;j-=lowbit(j))
		{
			sum[i][j]+=v;
		}
	}
}
int query(int x,int y)
{
	int ans=0;
	for(int i=x;i<=n;i+=lowbit(i))
	{
		for(int j=y;j<=n;j+=lowbit(j))
		{
			ans+=sum[i][j];
		}
	}	
	return ans;
}
ll p[N][N],h[N][N];
ll solve(int x,int y)
{
	return h[y][n]-h[y][n-x];
}
void update(int x1,int y1,int x2,int y2)
{
	diff[x1][y1]++;
	diff[x2+1][y1]--;
	diff[x1][y2+1]--;
	diff[x2+1][y2+1]++;
}
int main()
{
	speed();
		freopen("army.in","r",stdin);
	freopen("army.out","w",stdout);
	// freopen("army1.in","r",stdin);
	// freopen("in.in","r",stdin);
	// freopen("out1.out","w",stdout);
	cin>>n>>m>>c>>k>>q;
	for(int i=1;i<=c;i++)
	{
		cin>>a[i].x1>>a[i].y1>>a[i].x2>>a[i].y2;
		update(a[i].x1,a[i].y1,a[i].x2,a[i].y2);
	}	
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+diff[i][j];
			if(sum[i][j]>=k)mu[i]++;
			// if(sum[i][j]>=k)mu[i]++;
			// cout<<sum[i][j]<<" ";
		}
		// cout<<endl;
	}
	for(int y=1;y<=m;y++)
	{
		for(int i=1;i<=n;i++)
		{
			ll b=min(mu[i],m-mu[i]);
			p[y][i]=min<ll>(b,y/2)*(y-min<ll>(b,y/2));	
			
		}
		sort(p[y]+1,p[y]+1+n);	
		for(int i=1;i<=n;i++)
			h[y][i]=h[y][i-1]+p[y][i];		
	}

	int x,y;
	for(int i=1;i<=q;i++)
	{
		cin>>x>>y;
		cout<<solve(x,y)<<endl;
	}
	return 0;

}

T4暴力\(dp\)

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 2e6+5,mod=998244353;;
int n,q;
int st=1,ed;
int g[N][25];ll dp[N][25];
int len=0;
char s[N];
int xx[5]={0,1,2,1,2};
int yy[5]={0,2,1,-2,-1};
inline int solve(int ta,int tb)
{
	
	for(int i=st;i<=ed;i++)
		for(int j=1;j<=n;j++)
			dp[i][j]=0;
	dp[st][ta]=1;
	// cout<<st<<" "<<ed<<" "<<n<<endl;
	for(int i=st;i<=ed;i++)
	{
		for(int j=1;j<=n;j++)
		{
			if(dp[i][j]&&g[i][j])
			{
				for(int k=1;k<=4;k++)
				{
					int x=xx[k]+i,y=yy[k]+j;
					if(x>=st&&x<=ed&&y>=1&&y<=n&&g[x][y])
					{
						dp[x][y]=(dp[i][j]+dp[x][y])%mod;
					}
				}
			}
		}
	}
	return dp[ed][tb];
}
// int update(int l,int r)
// {
// 	for(int i=l;i<=r;i++)
// 		for(int j=1;j<=n;j++)
// }
int main()
{
	speed();
	freopen("chess.in","r",stdin);
	freopen("chess.out","w",stdout);
	cin>>n>>q;
	char opt[15];
	int x,y;
	while(q--)
	{
		cin>>opt;
		if(opt[0]=='A')
		{
			ed++;
			cin>>s+1;
			for(int i=1;i<=n;i++)
			{
				if(s[i]=='.')g[ed][i]=1;
			}
		}else if(opt[0]=='D')
		{
			st++;

		}else
		{
			cin>>x>>y;
			cout<<solve(x,y)<<endl;
		}
	}
	return 0;

}

T1 题意很容易读假 2-Coloring
image
如图,考虑一个方案合法,蓝、黄颜色所形成的连通块个数必须 \(\le 2\),否则一定不合法,而显然如果两种颜色连通块个数都为 \(1\) 也不合法,上图以蓝色连通块个数为 \(1\),黄色连通块个数为 \(2\) 为例
洛谷题解
我们要枚举的就是中间分隔开黄左右两部分的点\(A,B\),且\(A,B\)肯定在同一列,因为如果不在,那么必有一列中两个空位不相邻,那我们枚举就是\(O(n^2m)\)的复杂度,用前缀和优化一下,\(O(nm)\),考虑如何计算方案:
接着,也就是说存在一个分割点 \(i\),使得第一个连通块全部在第 \(i\) 列左侧,第二个连通块全部在第 \(i\) 列右侧,那么显然两个连通块与第 \(i\) 列的交点分别是一段不相交区间 \((l_1,r_1),(l_2,r_2)\),我们假设第一个连通块的区间在第二个连通块的区间的上方,也就是如图所示的情况,那么我们假设 \(j=r_1,k=l_2\)(当然如果 \(j=k\) 蓝色连通块会被一分为二,也就是蓝色、黄色连通块个数都为 \(2\) 的情况),那么显然第一个连通块与直线 \(x=i\) 的交中最下方的点的坐标就是 \((j,i)\)(即图中的点 A),第二个连通块与直线 \(x=i\) 的交中最上方的点就是 \((k,i)\)(即图中的点 B)。接下来考虑怎样计算方案数,隔板法是肯定没问题的,不过这里有一种更简便的理解方式,以计算 \(A\) 左上角的方案数为例,它等价于从最左上角的点走到 \(A\) 的方案数,但由于 \(A\) 是这段区间中最下方的点,因此最后一步必须是向下走的,因此左上角的方案数就是从最左上角的点走到 \(A\) 上方的点的方案数,另外四块也同理,如图所示:

对于 \((l_1,r_1)\)\((l_2,r_2)\) 下方的情况只需乘个 \(2\) 即可,因为所有 \((l_1,r_1)\)\((l_2,r_2)\) 上方的情况把它上下翻转都能够得到 \((l_1,r_1)\)\((l_2,r_2)\) 下方的情况,因此它们构成了一个双射。对于蓝色连通块个数为 \(2\),黄色连通块个数为 \(1\) 的情况其实很 simple,只需做整个网络关于 \(y=x\) 对称的图形即可,但是这样蓝色、黄色连通块个数都是 \(2\) 的情况会被算重,因此第二次计算的时候需要强制令 \(k-j\ge 1\),因为已经考虑过\(A=B\)的情况了,不必再加一遍了

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 2e5+5,mod=998244353;
inline int read()
{
	int x=0,f=1;char ch=getchar_unlocked();
	for(;ch<'0'||ch>'9';ch=getchar_unlocked())ch=='-'?f=-1:f=f;
	for(;ch>='0'&&ch<='9';ch=getchar_unlocked())x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
inline void write(int x)
{
	return x<0?(putchar_unlocked('-'),write(-x),void(0)):(x==0?void(0):(write(x/10),putchar_unlocked((x%10)|48),void(0)));
}
ll qpow(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;b>>=1;a=a*a%mod;}return ans;}
int n,m;ll fac[N],inv[N];
ll ways(int x,int y){return fac[x+y]*inv[x]%mod*inv[y]%mod;}
int main()
{
	// freopen("in.in","r",stdin);
	// freopen("out.out","w",stdout);
	// freopen("magic.in","r",stdin);
	// freopen("magic.out","w",stdout);	
	n=read();m=read();
	fac[0]=1;inv[0]=inv[1]=1;
	for(ll i=1;i<=N-5;i++)fac[i]=fac[i-1]*i%mod;
	for(ll i=2;i<=N-5;i++){
		inv[i]=(mod-mod/i)*inv[mod%i]%mod;
		// cout<<fac[i]<<endl;
		// inv[i]=qpow(fac[i],mod-2);
		// cout<<inv[i]<<" "<<qpow(fac[i],mod-2)<<endl;
	}
	for(ll i=2;i<=N-5;i++)
	{
		inv[i]=inv[i]*inv[i-1]%mod;
		// cout<<inv[i]<<" "<<qpow(fac[i],mod-2)<<endl;
	}
	ll sum=0,ans=0;
	for(int i=1;i<=m-1;i++)
	{
		sum=0;
		for(int j=1;j<=n-1;j++)
		{	
			sum=(sum+ways(i,j-1)*ways(i-1,n-j)%mod)%mod;
			ans=(ans+sum*ways(m-i-1,j)%mod*ways(m-i,n-j-1)%mod)%mod;
		}
	}
	n^=m^=n^=m;
	for(int i=1;i<=m-1;i++)
	{
		sum=0;
		for(int j=1;j<=n-1;j++)
		{	
			ans=(ans+sum*ways(m-i-1,j)%mod*ways(m-i,n-j-1)%mod)%mod;
			sum=(sum+ways(i,j-1)*ways(i-1,n-j)%mod)%mod;
			
		}
	}	
	// cout<<ans<<endl;
	write(ans*2%mod);
	return 0;
}

T2与P10238 [yLCPC2024] F. PANDORA PARADOXXX 类似
套路:删边维护很困难,所以倒着考虑加边,用并查集维护,
性质:一个连通块树的直径两个端点(深度最深)与另一个连通块树合并时,最长的一定在四个端点之中
求最远点无异于求直径,一个点到最远点的距离一定是到直径某个端点的距离
在维护连通块时,同样可以维护直径,新的直径两个端点一定在原先的4个端点之中

点击查看代码
#include <bits/stdc++.h>
#define speed() ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
#define ll long long
#define pb push_back
#define ull unsigned long long
#define pii pair<int,int>
#define lid (rt<<1)
#define rid (rt<<1|1)
#define ts cout<<"-------------------"<<endl
using namespace std;
const int N = 2e5+5;
int dfn[N],dep[N],f[N][25];
int n,m;vector <pii> edge[N],e;
inline int read()
{
	int x=0,f=1;char ch=getchar_unlocked();
	for(;ch<'0'||ch>'9';ch=getchar_unlocked())ch=='-'?f=-1:f=f;
	for(;ch>='0'&&ch<='9';ch=getchar_unlocked())x=(x<<3)+(x<<1)+(ch^48);
	return x*f;
}
inline void write(int x)
{
	return x<0?(putchar_unlocked('-'),write(-x),void(0)):(x==0?void(0):(write(x/10),putchar_unlocked((x%10)|48),void(0)));
}
struct Query
{
	int op,x;
}q[N];bool vis[N];

void dfs(int u)
{
	for(int i=1;i<=20;i++)f[u][i]=f[f[u][i-1]][i-1];
	dep[u]=dep[f[u][0]]+1;
	for(auto [to,id]:edge[u])
	{
		if(to==f[u][0])continue;
		f[to][0]=u;
		dfs(to);
	}
}
int lca(int  x,int y)
{
	if(dep[x]<dep[y])swap(x,y);
	for(int i=20;i>=0;i--)
		if(dep[f[x][i]]>=dep[y])x=f[x][i];
	if(x==y)return x;
	for(int i=20;i>=0;i--)
		if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
	return f[x][0];
}
int get(int u,int v){return dep[u]+dep[v]-2*dep[lca(u,v)];}
int fa[N];
int find(int x){if(fa[x]!=x)fa[x]=find(fa[x]);return fa[x];}
int ans,res[N],s[N][2],mx[N];
void merge(int u,int v)
{
	int fu=find(u),fv=find(v);
	// cout<<u<<" "<<v<<" "<<fu<<" "<<fv<<endl;
	fa[fu]=fv;
	int mm=0;
	int now[5]={0,s[fu][0],s[fu][1],s[fv][0],s[fv][1]};
	for(int i=1;i<=4;i++)
	{
		for(int j=i+1;j<=4;j++)
		{
			// cout<<now[i]<<" "<<now[j]<<" "<<get(now[i],now[j])<<endl;
			int dis=get(now[i],now[j]);
			if(mm<dis)
			{
				s[fv][0]=now[i],s[fv][1]=now[j];
				mm=dis;mx[fv]=dis;
			}
		}
	}
	// cout<<"DAWN"<<fv<<" "<<mx[fv]<<" "<<find(1)<<endl;
	ans=max(ans,mx[fv]);
}
int main()
{
	speed();
	// freopen("in.in","r",stdin);
	// freopen("out.out","w",stdout);
	freopen("block.in","r",stdin);
	freopen("block.out","w",stdout);	
	// freopen("block1.in","r",stdin);	
	// freopen("out.out","w",stdout);
	int u,v;n=read();m=read();
	e.pb({0,0});
	for(int i=1;i<=n;i++)fa[i]=i,s[i][0]=s[i][1]=i;
	for(int i=1;i<=n-1;i++)
	{
		u=read();v=read();
		edge[u].pb({v,i});edge[v].pb({u,i});
		e.pb({u,v});
	}
	dfs(1);
	for(int i=1;i<=m;i++)
	{
		q[i].op=read();
		// cout<<q[i].op<<endl;
		q[i].x=read();
		if(q[i].op==1)vis[q[i].x]=1;
	}
	for(int i=1;i<=n-1;i++)
	{
		if(vis[i])continue;
		// cout<<i<<endl;
		int x=e[i].first,y=e[i].second;
		if(dep[x]>dep[y])swap(x,y);
		merge(x,y);
	}
	for(int i=m;i;i--)
	{
		if(q[i].op==1)
		{
			// cout<<q[i].x<<endl;
			int x=e[q[i].x].first,y=e[q[i].x].second;
			if(dep[x]>dep[y])swap(x,y);
			merge(x,y);
		}else
		{
			// cout<<i<<" "<<q[i].x<<" "<<find(q[i].x)<<" "<<mx[find(q[i].x)]<<endl;
			int f=find(q[i].x);
			int x1=s[f][0],x2=s[f][1];
			res[i]=max(res[i],max(get(x1,q[i].x),get(q[i].x,x2)));
		}
	}
	for(int i=1;i<=m;i++)
	{
		// cout<<i<<endl;
		if(q[i].op==2){
			res[i]==0?(putchar_unlocked('0'),void(0)):write(res[i]);
			putchar_unlocked('\n');
		}		
	}

	return 0;
}

T3

军队

二维数点,线段树,扫描线,处理出\(<k\)

posted @ 2024-08-16 21:27  wlesq  阅读(14)  评论(0编辑  收藏  举报