多校冲刺 NOIP 20211111 模拟 (28)

冲了3个正解,结果一个挂了,哭了。。。。。

T1 嗑瓜子

水笔期望dp,不多阐述

T2 第 k 大查询

由于k<=50所以考虑找到这个数字前面第k个比它大的,和后面的数字进行区间匹配,

顺序删点保证里面的数字都是比当前数字大的,然后链表维护就行了

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int maxn=5e5+5;
int nxt[maxn],lst[maxn],n,a[maxn],bel[maxn],k;ll ans=0;
signed main()
{
	freopen("kth.in","r",stdin);
	freopen("kth.out","w",stdout);
	n=read(); k=read(); nxt[0]=1;
	for(int i=1;i<=n;i++) a[i]=read(),bel[a[i]]=i;
	for(int i=1;i<=n+1;i++) lst[i]=i-1,nxt[i]=i+1;
	for(int i=1;i<=n;i++)
	{
		int x=bel[i]; int cnt=0,from=x,to=x;
		if(n-i+1<k) break;
		while(from&&cnt<k) {cnt++;from=lst[from];}
		while(cnt<k) {to=nxt[to];cnt++;}
		while(from!=x&&to<=n)
		{
			ans=ans+1ll*(nxt[from]-from)*(nxt[to]-to)*i;
			from=nxt[from];to=nxt[to];
		}
		nxt[lst[x]]=nxt[x]; lst[nxt[x]]=lst[x];
	}
	printf("%lld\n",ans);
}

T3 树上路径

emmm细节有点多,样例全过了,一交就蛋了。。。。

肯定存在一条边把这两条路径分为两部分,那么枚举这条边(就是直接dfs)然后找到两端的联通块的直径更新答案

考虑如何找到两端的直径,首先维护出一个点子树里经过它的最长链和不经过它的最长链,然后再维护出自己兄弟子树里

通过与不通过兄弟自己的最长链,然后在dfs的时候直接传参就行了

#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define ll long long
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int maxn=5e5+5;
int n,ans[maxn],maxx[maxn],dps[maxn],mx[maxn],dep[maxn];
vector<int>vec[maxn],xd[maxn],dian[maxn]; vector<pii>zx[maxn];
int zd[maxn],cd[maxn],tong[maxn];
inline void dfs1(int x,int f)
{
	dep[x]=dep[f]+1;dps[x]=dep[x];mx[x]=1;
	for(int i=0;i<vec[x].size();i++)
	{
		int y=vec[x][i];
		if(y==f) continue; dfs1(y,x);
		maxx[x]=max(maxx[x],max(dps[y]-dep[x],max(maxx[y],mx[y])));
		mx[x]=max(mx[x],dps[x]-dep[x]+dps[y]-dep[x]+1);
		dps[x]=max(dps[x],dps[y]); zx[x].push_back(mp(0,0));
		xd[x].push_back(dps[y]-dep[x]);
		dian[x].push_back(y);
	}
	for(auto y:dian[x]) tong[dps[y]-dep[x]]++;
	if(xd[x].size()>=2)
	{
		sort(xd[x].begin(),xd[x].end());
		for(int i=0;i<dian[x].size();i++)
		{
			int y=dian[x][i];
			int tmp1=dian[x].size()-1,tmp2=dian[x].size()-2,tmp3=dps[y]-dep[x];
			if(tmp3==xd[x][tmp1]&&tong[xd[x][tmp1]]<=2) tmp1--,tmp2--;
			else if(tmp3==xd[x][tmp2]&&tong[xd[x][tmp2]]==1) tmp2--;
			zd[y]=xd[x][tmp1];if(tmp2>=0) cd[y]=xd[x][tmp2];
		}
	}
	for(int i=0;i<dian[x].size();i++){int y=dian[x][i];tong[dps[y]-dep[x]]--;}
	if(zx[x].size()>=2)
	for(int i=1;i<zx[x].size();i++)
	{int y=dian[x][i-1];zx[x][i].fi=max(max(zx[x][i-1].fi,dps[y]-dps[x]),max(maxx[y],mx[y]));}
	if(zx[x].size()>=2)
	for(int i=zx[x].size()-2;i>=0;i--)
	{int y=dian[x][i+1];zx[x][i].se=max(max(zx[x][i+1].se,dps[y]-dps[x]),max(maxx[y],mx[y]));}
}
inline void chmax(int &x,int y){x=max(x,y);}
inline void dfs2(int x,int f,int j,int bj)
{
	for(int i=0;i<dian[x].size();i++)
	{
		int y=dian[x][i];
		int tmp1=max(j+zd[y],max(bj,zd[y]+1));
		
		tmp1=max(tmp1,zd[y]+cd[y]+1);
		
		tmp1=max(max(zx[x][i].fi,zx[x][i].se),tmp1);
		chmax(ans[tmp1],max(maxx[y],mx[y]));
		chmax(ans[max(maxx[y],mx[y])],tmp1);
		dfs2(y,x,max(j+1,zd[y]+2),max(max(zd[y]+j,zd[y]+cd[y]+1),tmp1));
	}
}
signed main()
{
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	n=read();
	for(int i=1;i<n;i++) 
	{
		int x=read(),y=read();
		vec[x].push_back(y);
		vec[y].push_back(x);
	}
	dfs1(1,0);dfs2(1,0,1,0);ll sum=0;
	for(int i=n;i>=1;i--) ans[i]=max(ans[i],ans[i+1]);
	for(int i=1;i<=n;i++) sum+=ans[i];
	printf("%lld\n",sum);
}

T4 糖

单调队列优化一下贪心过程就OK了

#include<bits/stdc++.h>
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define int long long
using namespace std;
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
const int maxn=5e5+5;
int a[maxn],b[maxn],s[maxn],n,C,now,ans;
pii que[maxn];
signed main()
{
	freopen("candy.in","r",stdin);
	freopen("candy.out","w",stdout);
	n=read();C=read();
	for(int i=1;i<=n;i++) a[i]=read();
	for(int i=0;i<n;i++) b[i]=read(),s[i]=read();
	int head=1,tail=0;
	for(int i=0;i<n;i++)
	{
		int ji=0;
		while(head<=tail&&que[head].fi<=s[i]){ji+=que[head].se;++head;}
		if(ji){--head;que[head]=make_pair(s[i],ji);}
		while(head<=tail&&que[tail].fi>=b[i])
		{ans-=que[tail].fi*que[tail].se,now-=que[tail].se,--tail;}
		if(i!=n)
		{
			que[++tail]=mp(b[i],C-now);
			ans+=b[i]*(C-now);now=C;
			int len=a[i+1]-a[i];now-=len;
			while(head<=tail&&len>=que[head].se)len-=que[head].se,++head;
			if(len)que[head].se-=len;
		}
	}
	while(head<=tail)ans-=que[tail].fi*que[tail].se,tail--;;
	printf("%lld\n",ans);
}
posted on 2021-11-13 06:31  JYFHYX  阅读(34)  评论(0编辑  收藏  举报