csp-s模拟10

A. 欧几里得的噩梦

线性基,不会,咕咕咕

B. 清扫

赛时想到要分为两种操作了,也想到要把剩余未分配石头上传处理了,但是没想清楚操作之间的关系,冲着一堆样例的结论

就开始写分讨了,思路不是很清晰,然后因为绑包。。。似的很惨

对于一个节点,我们把它直接儿子当作叶子即可,上面的信息是其子树分配后需要处理的石头数,对于消去操作,可以选择

两个其子树内的叶子消,这样子树内的石头会2倍的减少,也可以一个子树内,一个子树外,,这样就是一起减少1,我们发现

根节点石头数必须小于其子树石头总数才可能有解,所以我们应该先选子树内的节点消,直到子树石头总数与根相同停止(能在

子树内处理的就不在子树外处理了),还有一些对节点数的限制,细节看代码吧

点击查看代码
#include<bits/stdc++.h>
#define int long long 
const int maxn=1e5+10;
using namespace std;
int n,a[maxn],head[maxn],to[maxn<<1],nxt[maxn<<1],tot,in[maxn],rt;
void add(int x,int y)
{
	to[++tot]=y;
	nxt[tot]=head[x];
	head[x]=tot;
}
void addm(int x,int y)
{
	add(x,y),add(y,x);
}

void lsx(int x,int fa)
{
	int sum=0,temp=0,t=0;
	for(int i=head[x];i;i=nxt[i])
	{
		int y=to[i];
		if(y==fa) continue;
		lsx(y,x);
		temp++,sum+=a[y],t=max(t,a[y]);
	}
	if(!temp)return;
	if(a[x]<ceil(1.0*sum/2)||sum<a[x]||t>a[x])
	{
		puts("NO");
		exit(0);
	}
//	cout<<x<<" "<<a[x]<<" "<<sum<<endl; 
	a[x]=a[x]*2-sum;
}

signed main()
{
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout); 
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<n;i++)
	{
		int x,y;
		cin>>x>>y;
		in[x]++,in[y]++;
		addm(x,y);
		if(in[x]>1)rt=x;
		if(in[y]>1)rt=y;
	}
	if(n==2)
	{
		if(a[1]==a[2])puts("YES");
		else puts("NO");
		return 0;
	}
	lsx(rt,0);
	if(a[rt]==0)puts("YES");
	else puts("NO");
	
	return 0;
}
/*
3
2 1 3
1 2
1 3

*/

C. 购物

先对数组排序,考虑新加进来一个数 \(a_i\) 的影响,它的统治区间是 \(\lceil\frac{a_i}{2}\rceil - a_i\),用 \(sum\) 表示前缀和,若 \(\lceil\frac{a_i}{2}\rceil\) 大于 \(sum_{i-1}\)

则在 $ sum_{i-1} - \lceil \frac{a_i}{2} \rceil $ 处产生了一段缺口,而 \(\lceil\frac{a_i}{2}\rceil - sum_i\) 一定是连续的,小于 \(a_i\) 的部分可以用 \(a_i\) 理解,而对于大于

\(a_i\) 的部分,因为 \(\lceil \frac{a_i}{2} \rceil>sum_{i-1}\) 所以这部分数都可以用 \(a_i+sum_{i-1}\) 理解

点击查看代码
#include<bits/stdc++.h>
#define int long long
const int maxn=1e5+10;
using namespace std;
int a[maxn],sum[maxn],n,q[maxn],l,r,ans;

signed main()
{
	freopen("buy.in","r",stdin);
	freopen("buy.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	sort(a+1,a+1+n);
	for(int i=1;i<=n;i++) sum[i]=sum[i-1]+a[i];
	ans=sum[n];
	for(int i=1;i<=n;i++)
	{
		if(ceil(1.0*a[i]/2)>sum[i-1])
		{
			ans-=(ceil(1.0*a[i]/2)-sum[i-1]-1);
		}
	}
	cout<<ans;

	return 0;
}
/*
3
181573206 28406510 456313

134537153
*/

D. ants

回滚莫队板子题,但是我不会。。。

只加不减的莫队,用并查集维护联通块实现加的操作

点击查看代码
#include<bits/stdc++.h> 
using namespace std;
const int maxn=1e5+10;
struct lsx{int l,r,pos,id;}q[maxn];
int n,m,a[maxn],ans[maxn],st[maxn],size[maxn],fa[maxn],res,top;
bool vis[maxn];
bool cmp(lsx a,lsx b){return a.pos==b.pos?a.r<b.r:a.pos<b.pos;}
int find(int x){return x==fa[x]?x:find(fa[x]);}
void merge(int x,int y)
{
	x=find(x),y=find(y);
	if(x==y)return ;
	if(size[x]>size[y])x^=y^=x^=y;
	fa[x]=y;
	size[y]+=size[x];
	st[++st[0]]=x;
}
void add(int x)
{
	vis[x]=1;
	if(vis[x-1]) merge(x,x-1);
	if(vis[x+1]) merge(x,x+1);
	res=max(res,size[find(x)]);
}
void del()
{
	while(st[0]>top)
	{
		size[find(st[st[0]])]-=size[st[st[0]]];
		fa[st[st[0]]]=st[st[0]];
		st[0]--;
	}
}

int main(){
	freopen("ants.in","r",stdin);
	freopen("ants.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m;
	int t=sqrt(n);
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=m;i++)
	{
		cin>>q[i].l>>q[i].r;
		q[i].pos=(q[i].l-1)/t+1;
		q[i].id=i;
	} 
	sort(q+1,q+m+1,cmp);
	int l,r,pos;
	for(int i=1;i<=m;i++)
	{ 
		if(q[i].pos!=q[i-1].pos)
		{
			for(int j=1;j<=n;j++)
			{
				fa[j]=j;
				vis[j]=0;
				size[j]=1;
			}
			res=st[0]=0;
			l=pos=q[i].pos*t+1;
			r=l-1;
		}
		if(q[i].pos==(q[i].r-1)/t+1)
		{
			int now=1,maxx=1;
			for(int j=q[i].l;j<=q[i].r;j++) st[++st[0]]=a[j];
			sort(st+1,st+1+st[0]);
			for(int j=1;j<=st[0];j++)
			{
				if(st[j]==st[j-1]+1&&j>1) now++;
				else now=1;
				maxx=max(maxx,now);
			}
			ans[q[i].id]=maxx;
			st[0]=0;
		}
		else
		{
			while(r<q[i].r) add(a[++r]);
			int flag=res;
			top=st[0];
			while(l>q[i].l) add(a[--l]);
			ans[q[i].id]=res;
			res=flag;
			while(l<pos) vis[a[l++]]=0;
			del();
		}
	}
	for(int i=1;i<=m;i++) cout<<ans[i]<<'\n';
	
    return 0;
}

stars

image

posted @   _君の名は  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· 使用C#创建一个MCP客户端
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· Windows编程----内核对象竟然如此简单?
点击右上角即可分享
微信分享提示