2022.7.11 AGC054E&AGC023D&AGC022D

AGC054E ZigZag Break

题意:给定 \(N,A\) 计数满足如下条件的排列:\(P_1=A\);可以重复一下操作使得 \(P\) 只剩两个元素:选择三个连续的位置 \(x,y,z\),若有 \(P_y\) 为三个元素中的最大或最小值,则是删除 \(P_y\)。需要 \(O(n)\) 预处理 \(O(1)\) 回答。

题解:结论:不妨假设 \(P_1\leqslant P_n\),存在位置 \(1\leqslant i\leqslant n-1\),使得 \(P_1\geqslant P_i,P_{i+1}\geqslant P_n\),计数部分是 trivial 的。

AGC023D Go Home

瞎扯:考虑一手正难则反。考虑倒序轨迹,若 \(P_1\geqslant P_n\),则走到 \(1\) 之前一定不会走到 \(n\),所以 \(n\) 的志愿与 \(1\) 相同,\(P_1\leftarrow P_1+P_n\) 后删掉 \(n\) 递归即可。注意要记录此时的位置以便计算贡献。

#include<bits/stdc++.h>
using namespace std;
#define inf 1e9
const int maxn=2e5+10;
const int mod=1e9+7;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();}
	return x*f;
}
long long ans,P[maxn];
int n,m,X[maxn];
inline void solve(int l,int r,int t){
	if(m<=X[l])return void(ans+=X[r]-m);
	if(m>=X[r])return void(ans+=m-X[l]);
	if(P[l]>=P[r])P[l]+=P[r],solve(l,r-1,l),ans+=(t==r?X[r]-X[l]:0);
	else P[r]+=P[l],solve(l+1,r,r),ans+=(t==l?X[r]-X[l]:0);
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=n;i++)X[i]=read(),P[i]=read();
	solve(1,n,P[1]<P[n]?1:n);
	printf("%lld\n",ans);
	return 0;
}
posted @ 2022-07-13 00:13  syzf2222  阅读(48)  评论(6编辑  收藏  举报