csp-s模擬10

_君の名は發表於2024-10-09

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

相關文章