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;
}