ICPC2024沈阳 D逆序对+博弈 G计算几何+交互 M缩点+判非零环
博弈 逆序对 循环移位两个人分别操作自己的排列ab,每次可以交换两个元素,要求交换之后∑aibi变大。轮流进行,如果一个人没法操作了,就输了。每次询问会把一个人的排列的一个区间循环移位,然后需要输出此时先手必胜还是必败注意到∑aibi最大就是两个排列完全一样,进一步,越接近完全一样,式子就越大。所以一个人每次交换两个元素,想让式子变大,1必须是逐步排序的一个过程,也就是要至少消除一个逆序对
D
博弈 逆序对 循环移位
两个人分别操作自己的排列a,ba,ba,b,每次可以交换两个元素,要求交换之后∑aibi\sum a_ib_i∑aibi变大。轮流进行,如果一个人没法操作了,就输了。
每次询问会把一个人的排列的一个区间循环移位,然后需要输出此时先手必胜还是必败
注意到∑aibi\sum a_ib_i∑aibi最大就是两个排列完全一样,进一步,越接近完全一样,式子就越大。所以一个人每次交换两个元素,想让式子变大,1必须是逐步排序的一个过程,也就是要至少消除一个逆序对。这里的逆序对,是把一个排列作为基准,计算另一个排列的逆序对。
手玩样例会发现,先手是否必胜,由初始逆序对的奇偶性决定。这有两个切入角度,一是这是博弈,博弈一个经典问题就是守恒量,守恒量里一个经典问题就是奇偶性,所以可以先找一下奇偶对答案的影响。另一个更严谨的分析是,swapswapswap操作,每次会使得逆序对奇偶反转,这是经典结论。也就是,初始和结束状态的逆序对奇偶都是确定的,每次一个人操作会反转奇偶性,那么初始逆序对是奇数,则先手必胜,反之先手必败。
到这里都简单,但问题是每次会对一个区间循环移位,然后问先手是否必胜。看起来很难办,但不要慌,注意到循环移位对逆序对奇偶的影响,也是个经典问题。根据区间长度和循环移位次数的奇偶,实际上可以O(1)O(1)O(1)地确定对逆序对奇偶的影响,也就能确定操作后先手是否必胜。这里不会推,可以观察样例,也能得到区间长度和次数奇偶对逆序对的影响。
G
计算几何 交互
一个nnn个点的简单多边形,用不超过n−2n-2n−2次询问,确定这个多边形的面积。每次可以得到一个x=Cx=Cx=C的直线,在位于多边形边界上和内部的部分的长度
记我们询问得到的这个东西是个函数f(x)f(x)f(x),那么我们要求的面积,实际上就是f(x)f(x)f(x)在下标范围的内的积分。
并且,多边形的nnn个点至多把xxx轴分成了n−1n-1n−1个区间,每个区间内,这个函数都是分段线性的。线性的,只要两个点就能解出函数表达式,就能计算积分。对于一个区间[xi,xi+1][x_i,x_{i+1}][xi,xi+1],如果xi,xi+1x_i,x_{i+1}xi,xi+1上都只有一个点,我们直接询问f(xi),f(xi+1)f(x_i),f(x_{i+1})f(xi),f(xi+1)即可确定这一段上的解析式。如果某一个xxx上有不止一个点,在这里两段函数就不连续了,询问得到的可能上另一段区间的端点的函数值,不能用来计算这一段的表达式,那么需要在区间内部(xi,xi+1)(x_i,x_{i+1})(xi,xi+1)选一个点询问,显然这样询问次数也不会超的,因为这样一次询问能解决不止一个点。
M
缩点+dfsdfsdfs判非零环+拓扑排序
mmm个操作,每个都形如,对模nnn余数为aaa的元素,加bbb,每个询问给一个起始元素,问随意使用这些操作,能否到达无穷个元素。
显然这些操作构成了一个图。而这个问题等价于能否在图上无限移动,且元素值的序列是发散的。在图上无限移动,一般等价于进入一个环,这里要求元素值序列发散,则是还要求进入的环,边权和不为0,这样每转一圈,元素值就会+∑wi+\sum w_i+∑wi。
有多次询问,考虑预处理,反向连边,缩点,从sccsccscc对应点出发拓扑排序,就能记录每个元素出发,能否到达一个环。准确来说是对于模nnn的每个余数除法,能否进入一个环,回答询问时直接查表即可。
这里的sccsccscc还要求至少存在一个非零环,这看起来能转化为是否存在正环,负环,可以用spfaspfaspfa判负环,但太慢。实际上非零环,直接对sccsccscc进行dfsdfsdfs,设dfsdfsdfs起点为xxx,如果能访问到一个点yyy,有两个不同深度,那么x→yx→yx→y存在两条边权和不同的路径,并且由于这是sccsccscc,一定也存在一条y→xy→xy→x的路径,把他们组合起来,就形成了两个经过x,yx,yx,y的环,且环的边权和不同,那么这两个环的边权和肯定不全为000,也就至少存在一个非零环
所以我们先对每个sccsccscc进行上述dfsdfsdfs,只对于存在非零环的sccsccscc作为拓扑排序起点。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10;
int in[N],dfn[N],co[N],low[N],s[N],ind[N],top,cnt,tot;
vector<pair<int,int>>a[N];
vector<int>b[N];
int vis[N],loop[N],d[N];
bool ok;
inline void tarjan(int x){
dfn[x]=low[x]=++cnt;
s[++top]=x;
ind[x]=1;
for(auto &[v,w]:a[x]){
if(!dfn[v]){
tarjan(v);
low[x]=min(low[x],low[v]);
}
else if(ind[v]){
low[x]=min(low[x],low[v]);
}
}
if(low[x]==dfn[x]){
++tot;
while(1){
int X=s[top--];
co[X]=tot;
ind[X]=0;
if(!(x^X)){
break;
}
}
}
}
void dfs(int u,int color){
vis[u]=1;
for(auto &[v,w]:a[u]){
if(co[v]!=color)continue;
if(vis[v]){
if(d[v]!=d[u]+w){
ok=1;
}
}
else{
d[v]=d[u]+w;
dfs(v,color);
}
}
}
void solve() {
int n,m,Q;
cin>>n>>m>>Q;
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
u%=n;
u=(u+n)%n;
int nxt=(u+v)%n;
nxt=(nxt+n)%n;
a[nxt].push_back({u,v});
}
for(int i=0;i<n;i++){
if(!dfn[i]){
tarjan(i);
}
}
vector<vector<int>>scc(tot+1);
for(int i=0;i<n;i++){
scc[co[i]].push_back(i);
for(auto &[v,w]:a[i]){
if(co[i]^co[v]){
b[co[i]].push_back(co[v]);
in[co[v]]++;
}
}
}
for(int i=1;i<=tot;i++){
int x=scc[i][0];
ok=0;
dfs(x,i);
if(ok){
loop[i]=1;
}
}
queue<int>q;
for(int i=1;i<=tot;i++){
if(!in[i]){
q.push(i);
}
}
while(q.size()){
int u=q.front();
q.pop();
for(int v:b[u]){
loop[v]|=loop[u];
if(--in[v]==0){
q.push(v);
}
}
}
while(Q--){
int x;
cin>>x;
x=(x%n+n)%n;
if(loop[co[x]]){
cout<<"Yes\n";
}
else{
cout<<"No\n";
}
}
}
signed main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int T=1;
// cin >> T;
while (T--) {
solve();
}
}
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)