首页 > 其他分享 >CSP 模拟 37

CSP 模拟 37

时间:2024-10-03 16:34:45浏览次数:6  
标签:min int 37 必败 && fi CSP 模拟 dis

A median

如果保证每个数互不相同,直接统计每个序列中小于 \(x\) 和大于 \(x\) 的数量就好。
但是有重复的数,答案会算重,考虑给每一个数一个独一无二的特征,保证满足大小关系,直接给所有数排个序后,记录排序后的位置即可。时间复杂度 \(\mathcal{O}(n\log n)\)。

B travel

当 \(k\to\infty\) 时,而 \(f(x,y)\) 不为常量,则一定有环,两种情况:存在二元及以上的环,或者存在一条有两个自环的路径。拓扑可以同时处理这两个东西。

C game

首先如果只有一个数是必胜,考虑加进来一个数。
如果有两个 \(1\) 是必败,如果不是两个 \(1\),可以理解为谁在两个 \(1\) 的局面时成为先手,谁就必败,可以将两个数同时减去 \(1\),同理,之后的局面也能减去 \(1\),故可以直接减去较小数,剩下另一个。得出两个数的结论:当且仅当两数相等时,是先手必败局面。
考虑三个数的情况,根据差分的和小于最大值,先手可以对最大值进行操作,使得剩下两个数相等,所以三个数的时候是先手必胜。
推广到四个数:与两个数同理,谁在两个 \(1\) 的局面时成为先手,谁就必败,四个数同时减去最小值,如果剩三个,先手必胜,如果剩两个,此时最小值有两个,考虑剩下两个是否相等,如果剩一个,先手必胜,不剩也是先手必胜,所以我们得到四个数的结论:当且仅当相同的数两两配对时,先手必败。
后面的推广也类似,所以得出结论:当且仅当 \(n\) 为偶数且相同的数两两配对时,先手必败。
考虑严谨的证明:

  • 由必败状态操作后,一定会对数做出更改,无法回到必败状态。
  • 当前是必胜状态,如果 \(n\) 为奇数,根据差分的和小于最大值,先手可以对最大值进行操作,可以让所有数两两相等配对,剩下偶数个数。
  • 当前是必胜状态,如果 \(n\) 为偶数,根据差分的和小于最大值,先手可以对最大值进行操作,可以让 \(n-2\) 个数两两相等配对,剩下一个最小的数,而最大数经过操作之后一定可以等于这个最小数,这个直接考虑把数画成柱状图证明。

D counter

像最短路,考虑中转点,假设由 \(l\) 到 \(r\),由于每次最多移动 \(9\),所以一定会经过 \([mid-4,mid+4]\) 中的某些点,然后就可以二合并,考虑猫树分治即可,路径一定不会超出目标过远,差不多三十左右的距离。当距离不远时,查询效率极其低下,这时直接暴力即可。

#include<bits/stdc++.h>
#define fi first
#define se second
#define eb emplace_back
#define fo(i,s,t) for(int i=s;i<=t;++i)
typedef long long ll;
typedef unsigned long long ull;
inline int read(){char ch=getchar();int x=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'&&ch<='9';ch=getchar())x=(x<<3)+(x<<1)+(ch^48);return x*f;}
const int N=1e5+300,LEN=1e5+30,inf=1e9;
int n,to[20][10][N],re[20][10][N],lastans,dis[N];
std::vector<int> in[N],out[N];
inline void build(int p,int l,int r){
    if(r-l<=30)return ;
    if(l==r)return;
    int fal=std::max(0,l-30),far=r+30;
    int mid=l+r>>1;
    int L=std::max(l,mid-4),R=std::min(r,mid+4);
    for(int s=L;s<=R;++s){
        std::fill(dis+fal,dis+far+1,-1);
        std::queue<std::pair<int,int>> q;
        q.push({s,0});
        while(!q.empty()){
            auto it=q.front();q.pop();
            if(dis[it.fi]>=0)continue;
            dis[it.fi]=it.se;
            for(int v:out[it.fi])if((dis[v]==-1)&&(v>=fal)&&(v<=far))q.push({v,it.se+1});
        }
        for(int i=l;i<=r;++i)to[p][s-L+1][i]=dis[i];
        std::fill(dis+fal,dis+far+1,-1);
        q.push({s,0});
        while(!q.empty()){
            auto it=q.front();q.pop();
            if(dis[it.fi]>=0)continue;
            dis[it.fi]=it.se;
            for(int v:in[it.fi])if((dis[v]==-1)&&(v>=fal)&&(v<=far))q.push({v,it.se+1});
        }
        for(int i=l;i<=r;++i)re[p][s-L+1][i]=dis[i];
    }
    build(p+1,l,mid);build(p+1,mid+1,r);
}
inline int query(int p,int l,int r,int x,int y){
    if(x==y)return 0;
    if(std::abs(x-y)<=30){
        int fal=std::max(0,std::min(x,y)-30),far=std::max(x,y)+30;
        std::fill(dis+fal,dis+far+1,-1);
        std::queue<std::pair<int,int>> q;
        q.push({x,0});
        while(!q.empty()){
            auto it=q.front();q.pop();
            if(dis[it.fi]>=0)continue;
            dis[it.fi]=it.se;
            if(it.fi==y)break;
            for(int v:out[it.fi])if((dis[v]==-1)&&(v>=fal)&&(v<=far))q.push({v,it.se+1});
        }
        return dis[y];
    }
    int mid=l+r>>1;
    if((x<=mid&&y>mid)||(x>mid&&y<=mid)){
        int L=std::max(l,mid-4),R=std::min(r,mid+4);
        int min=inf;
        for(int i=L;i<=R;++i)if(re[p][i-L+1][x]>=0&&to[p][i-L+1][y]>=0){
            min=std::min(min,re[p][i-L+1][x]+to[p][i-L+1][y]);
        }
        return min==inf?-1:min;
    }
    if(y<=mid&&x<=mid)return query(p+1,l,mid,x,y);
    else return query(p+1,mid+1,r,x,y);
}
signed main(){
    freopen("counter.in","r",stdin);freopen("counter.out","w",stdout);
    // freopen("in.in","r",stdin);freopen("out.out","w",stdout);
    std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
    for(int i=1;i<=LEN+30;++i){
        int zc=i;
        bool mp[10]={0};
        while(zc){
            int w=zc%10;
            zc/=10;
            if(!w||mp[w])continue;
            mp[w]=1;
            out[i].eb(i-w);in[i-w].eb(i);
            out[i].eb(i+w);in[i+w].eb(i);
        }
    }
    build(0,0,LEN);
    int T=read();
    while(T--){
        int x=read()^(lastans+1),y=read()^(lastans+1);
        std::cout<<(lastans=query(0,0,LEN,x,y))<<'\n';
    }
}

总结

咋一点博弈论都不会啊,这场有效时间没超过两个小时,后面就在坐牢,感觉已经对计数和博弈产生了畏难情绪,感觉比较寄。
以后静下心来慢慢找规律,学过的东西要运用起来。

标签:min,int,37,必败,&&,fi,CSP,模拟,dis
From: https://www.cnblogs.com/Ishar-zdl/p/18445771

相关文章

  • 2024/10/2 CSP-S daimayuan模拟赛复盘
    2024/10/2CSP-Sdaimayuancontestlink(Day7)A.序列题面描述给你一个序列\(r_1,r_2,\dots,r_n\),问有多少非负整数序列\(x_1,x_2,\dots,x_n\)满足:对于所有\(i\),\(0\leqx_i\leqr_i\)。满足\(x_1|x_2|…|x_n=x_1+x_2+⋯+x_n\),左边为二进制或。输出答案对......
  • 10月份模拟赛总结
    2024.10.3:能够感受到出题人深深的恶意,扔了道zak没场切的交互,甚至2e5的输出关同步流被卡了。A:一共只有$25n$种本质不同的操作,不妨求出每种操作后的新串的平方子串个数,最后取其中最大值即可。跨过它们的平方子串(包括修改后新生成的)的贡献。记$L=\min(LCS(a,b),l......
  • CSP-J模拟赛补题报告
    前言最SB的一次&做的最差的一次T1:AC100pts......
  • 南沙C++信奥赛陈老师解一本通题 2099:【23CSPJ普及组】公路(road)
    ​ 2099:【23CSPJ普及组】公路(road)时间限制:1000ms      内存限制:524288KB提交数:3793   通过数: 1575【题目描述】小苞准备开着车沿着公路自驾。公路上一共有 nn 个站点,编号为从 11 到nn。其中站点 ii 与站点i+1i+1 的距离为vivi 公里。......
  • 暑期模拟赛总结(下)
    8/1rnk15,\(90+0+60+30=180\)。T1集合题意:给定一个由\(0\simn-1\)的数组成的集合\(S\),求从\(S\)中取出\(k\)个元素的期望MEX是多少。对\(998244353\)取模。解析:简单组合数学。考虑对于一种选法的MEX是\(x\),当且仅当\(0\simx-1\)的所有数都被选择且\(x\)自......
  • 1002模拟赛
    \(T1\):题面注意:大凡求和求积的变量都要想想要不要开\(long\\long\)别人的一个很好的思路:这道题实在逆序对(\(n,n-1,..1\))上加限制,一串连续的1进行一个\(reverse\)。这给我们的启示是:当同时有两个限制(比如这题中的逆序对数最多和大小限制),可以先考虑一个,看看能产生什么,再把另......
  • 2024/10/2 CSP-S模拟赛
    B好题。这题其实是原题,在大工VS辽实的T3里出现过,基本是一摸一样。对于观看这个题解呢,我的理解是把两个结合起来观看,分别是这个和这个,结合起来看的话无论是从感官还是从方便理解来看都很舒服。好了,接下来我们说一下这个题的思路。你考虑,你在一段长度为\(m\)的区间里至少要选......
  • AtCoder Beginner Contest 373
    省流版A.暴力即可B.求出字母位置,绝对值相加即可C.显然答案为两个数组的最大值的和D.注意直接BFS的点权范围不超过题目范围,直接BFS即可E.发现单调性,二分票数,用前缀和\(O(1)\)判断可行性即可F.朴素背包DP,相同重量的物品一起考虑,用优先队列求解\(l\)个相同重量物品最大......
  • 2024/10/02 模拟赛总结
    暴力挂惨了,\(0+0+5+0=5\)#A.躲避技能评价:人机高精度由于边权是正数,多走一条边一定更劣,所以能在子树内解决的就尽量不要出来那么对于每一条边,它被遍历的次数是子树内起点与终点数量之差直接枚举每一条边,算答案即可人机高精度//BLuemoon_#include<bits/stdc++.h>using......
  • 题解:P11137 [APC001] B - Checker
    注意到每个字符串长度相同,所以我们可以按照题意逐个遍历小K的题目和所有题库里的题目,统计相同位置字符相同的个数,如果大于\(\left\lceil\frac{k}{2}\right\rceil\),这两个题目就是重题。代码:#include<bits/stdc++.h>usingnamespacestd;boolc(stringa,stringb){in......