Codeforces Round 1022 (Div. 2)(A~D,D赛后补的)
比赛链接:https://codeforces.com/contest/2108
最近cf比赛状态不行,连掉了4场,好在这场不掉了。有时不得不感慨一下,多用手画画会优于只思考
A. Permutation Warm-Up
思路:不妨先不排列从小到大排,这样子为0,随后发现任意移动两个数字其变化数值一定是偶数,然后开始又是0。随后可以手枚下,可发现最大值到0的偶数都可以出现,所以答案应该是倒序排后的值(最大值)/2+1
虽说是签到题,但是开局盯了半天没看出来,直接跳B然后倒开A了
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll long long
// #define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
// inline ll read()//快读
// {
// register ll 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 << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
// c = getchar();
// }
// return x * f;
// }
ll gcd(ll x, ll y)
{
if (y == 0)return x;
else return gcd(y, x % y);
}
void fio()//加速流
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
struct s
{
ll l, r;
friend bool operator<(const s& a, const s& b)
{
return a.l< b.l;
};
};
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为右边开始的逆时针,后面四个为角落
ll zs[2500000];
ll cnt=0;
void ola(ll x)
{
vector<bool>vis(x+5);
for(ll i=2;i<=x;i++)
{
if(!vis[i])zs[++cnt]=i;
for(ll j=1;i*zs[j]<=x;j++)
{
vis[i*zs[j]]=1;
if(i%zs[j]==0)break;
}
}
}
int main()
{
fio();
ll t=1;
// ola(100000);
cin>>t;
while (t--)
{
ll n;
cin>>n;
ll ans=0;
for(ll i=1;i<=n;i++)
{
ans+=abs(n-i+1-i);
}
cout<<ans/2+1<<endl;
}
return 0;
}
B. SUMdamental Decomposition
思路:
其实这道题可以更简单些:
如果x=0:如果n=1,-1.如果n为偶数,n;如果n为大于1的奇数,n-3+6(拿出三个数凑出1,2,3,剩下n-3(偶数)个数为1即可)
如果n为奇数,x+n-1.
如果n为偶数:如果x的二进制的权数大于等于2,n-2+x(我就把x拆成两部分,剩下偶数个位置填1);如果x的二进制的权数为1,如果x=1,那么可以拿出两个位置,一个填3,一个填2(3 xor 2=1),剩下填1,否则一个位置填x+1,剩下位置填1,答案为n+x。
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll long long
// #define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
// inline ll read()//快读
// {
// register ll 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 << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
// c = getchar();
// }
// return x * f;
// }
ll gcd(ll x, ll y)
{
if (y == 0)return x;
else return gcd(y, x % y);
}
void fio()//加速流
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
struct s
{
ll l, r;
friend bool operator<(const s& a, const s& b)
{
return a.l< b.l;
};
};
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为右边开始的逆时针,后面四个为角落
ll zs[2500000];
ll cnt=0;
void ola(ll x)
{
vector<bool>vis(x+5);
for(ll i=2;i<=x;i++)
{
if(!vis[i])zs[++cnt]=i;
for(ll j=1;i*zs[j]<=x;j++)
{
vis[i*zs[j]]=1;
if(i%zs[j]==0)break;
}
}
}
int main()
{
fio();
ll t=1;
// ola(100000);
cin>>t;
while (t--)
{
ll n,x;
cin>>n>>x;
if(x==0)
{
if(n==1)cout<<-1<<endl;
else if(n&1)cout<<n-3+6<<endl;
else cout<<n<<endl;
}
else if(x==1)
{
if(n&1)cout<<n<<endl;
else cout<<n+2-1+2<<endl;
}
else if(n==1)
{
cout<<x<<endl;
}
else
{
ll cnt=0;
for(ll j=0;j<=60;j++)
{
if((1ll<<j)&x)
{
cnt++;
}
}
if(cnt>=n)cout<<x<<endl;
else if((n-cnt)%2==0)
{
cout<<x+(n-cnt)<<endl;
}
else
{
cout<<x+(n-cnt)+1<<endl;
}
}
}
return 0;
}
C. Neo's Escape
思路:注意题目说的机器人移动是只对一个机器人移动,那么我很容易可以想到,如果一个连通且相等的数,那么其只要放一个机器人我就能全拿了,由此我们可以进行分块和离散化。
分完快后,我们从数值大的块进行遍历,每次通过判断区间左边和右边有没有紧邻标记(走过的)格子来确定是否有机器人能过来(从而判断这个块要不要放机器人),遍历完后,再遍历一遍这个块打个标记即可
不知道有没有人和我一样一开始以为全机器人一起移动,QWQ。不看样例的后果
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll long long
// #define lowbit(x) (x & -x)
#define endl "\n"// 交互题记得删除
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
// inline ll read()//快读
// {
// register ll 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 << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
// c = getchar();
// }
// return x * f;
// }
ll gcd(ll x, ll y)
{
if (y == 0)return x;
else return gcd(y, x % y);
}
void fio()//加速流
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
struct s
{
ll l, r;
friend bool operator<(const s& a, const s& b)
{
return a.l< b.l;
};
};
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为右边开始的逆时针,后面四个为角落
ll zs[2500000];
ll cnt=0;
void ola(ll x)
{
vector<bool>vis(x+5);
for(ll i=2;i<=x;i++)
{
if(!vis[i])zs[++cnt]=i;
for(ll j=1;i*zs[j]<=x;j++)
{
vis[i*zs[j]]=1;
if(i%zs[j]==0)break;
}
}
}
int main()
{
fio();
ll t=1;
// ola(100000);
cin>>t;
while (t--)
{
ll n;
cin>>n;
vector<ll>a(n+5);
vector<ll>b(n+5);
vector<pair<ll,ll>>g[n+5];
ll kk=1e18;
set<ll>f;
map<ll,ll>e;
vector<bool>vi(n+5,0);
for(ll i=1;i<=n;i++)cin>>a[i],f.insert(a[i]),b[i]=i;
ll co=0;
for(auto j:f)
{
if(e.find(j)==e.end())e[j]=++co;
else continue;
}
ll u=-1;
ll l=0,r;
for(ll i=1;i<=n;i++)
{
ll d=e[a[i]];
if(u!=d)
{
if(u>=0)g[u].push_back({l,r});
l=r=i;
u=d;
}
else
{
r++;
}
}
if(u>=0)g[u].push_back({l,r});
ll ans=0;
for(ll i=co;i>=1;i--)
{
for(auto [l,r]:g[i])
{
if(vi[l-1]==0&&vi[r+1]==0)
ans++;
for(ll u=l;u<=r;u++)vi[u]=1;
}
}
cout<<ans<<endl;
}
return 0;
}
D. Needle in a Numstack
思路:可以从前k个后最后k个入手,其必定分别属于A和B。首先n=2 * k,这个直接有解了,先判掉。随后可以通过2 * k(2 * 50(最坏))次询问得到前k个和后k个,又由于说连续k个,没有重复项,那么我们可以得出其A和B中的数并定按照某个周期排列(但是不一定能走完整个周期),他的周期一定是k,所有前k个位置模k,后k个位置模k,根据前后每个数字对应位置的模数,一直比到模数不一样的数。如果全一样,那必定多解。随后我们通过这个两个位置去二分得出左右边界(合法的,<=25 * 2),其大小小于等于100.至此边界得出.随后直接询问这个区间,至此询问次数不到250次。因为这个区间的左端点是符合A的,右端点是符合B的。我们可以暴力枚举A的边界,100 * 100.如何看合不合法?那就看枚举出的这个区间是否符合A的数字出现的周期性,枚举完后也要看看另一个区间是否符合B的周期性。如果两个都符合才是一个正确答案,至此答案得出。
#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<cstring>
#include<math.h>
#include<time.h>
#include<random>
#include<functional>
#include<stack>
#include<unordered_map>
#include<string>
#include<bitset>
#define ll long long
// #define lowbit(x) (x & -x)
// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;
using namespace std;
mt19937 rnd(time(0));
const ll mod = 1e9;
//const ll p=rnd()%mod;
#define F first
#define S second
// tree<ll,null_type,less<ll>,rb_tree_tag,tree_order_statistics_node_update>;find_by_order(k),找第k位(从小到大)的数字,order_of_key(x),x的排名
ll ksm(ll x, ll y)//快速幂
{
ll ans = 1;
x %= mod;
while (y)
{
if (y & 1)
{
ans = ans * x % mod;
}
x = x * x % mod;
y >>= 1;
}
return ans % mod;
}
ll gcd(ll x, ll y)
{
if (y == 0)
return x;
else
return gcd(y, x % y);
}
ll lcm(ll x, ll y)
{
x /= gcd(x, y);
return y * x;
}
// inline ll read()//快读
// {
// register ll 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 << 3) + (x << 1) + (c ^ 48); //等价于x*10+c-48,使用位运算加速
// c = getchar();
// }
// return x * f;
// }
void fio()//加速流
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
}
struct s
{
ll l, r;
friend bool operator<(const s& a, const s& b)
{
return a.l < b.l;
};
};
ll e1[8] = { 0,1,0,-1,1,1,-1,-1 };
ll e2[8] = { 1,0,-1,0,1,-1,-1,1 };//前面四个为右边开始的逆时针,后面四个为角落
ll q(ll x)
{
cout << "? " << x << endl;
cout.flush();
cin >> x;
return x;
}
ll dd[2500000];
ll a[2500000];
int main()
{
fio();
ll t;
cin >> t;
while (t--)
{
ll n, k;
cin >> n >> k;
if (n == k * 2)cout << "! " << k << " " << k << endl;
else
{
ll cs = 0;
ll ok = 1;
ll l = -1, r = -1;
vector<ll>c1(k + 5), c2(k + 5);
for (ll i = 1; i <= k; i++)
{
a[i] = q(i);
a[n - k + 1 + i - 1] = q(n - k + 1 + i - 1);
c1[a[i]] = i;
c2[a[n - k + 1 + i - 1]] = n - k + 1 + i - 1;
}
for (ll i = 1; i <= k; i++)
{
if (c1[i] % k == c2[i] % k)cs++;
else if (l == -1)
{
ll l1 = 0, r1 = 1e6;
while (l1 <= r1)
{
ll mid = l1 + r1 >> 1;
ll pd = 0;
if (mid * k + c1[i] > n)pd = 1;
else if (q(mid * k + c1[i]) != i)pd = 1;
if (pd)r1 = mid - 1;
else l1 = mid + 1;
}
//cout << 56 << endl;
l = r1 * k + c1[i];
l1 = 0, r1 = 1e6;
while (l1 <= r1)
{
ll pd = 0;
ll mid = l1 + r1 >> 1;
if (c2[i] - mid * k <= 0)pd = 1;
else if (q(c2[i] - mid * k) != i)pd = 1;
if (pd)r1 = mid-1;
else l1 = mid + 1;
}
r = c2[i] - r1 * k;
break;
}
}
if (cs == k)cout << "! -1" << endl;
else
{
l = max(l, k);
r = min(r, n - k + 1 - 1);
//cout<<l<<" "<<r<<endl;
for (ll i = l; i <= r + 1; i++)dd[i] = q(i);
ll ans = 0; ll ko = 0;
for (ll i = l; i <= r; i++)
{
ll d1 = c1[dd[l]], d2 = c2[dd[i + 1]];
ll len = 0;
for (ll j = l; j <= i; j++)
{
if (d1 == k + 1)d1 = 1;
if (a[d1] == dd[j])len++;
d1++;
}
if (len == i - l + 1)
{
len = 0;
// ans=i;
for (ll j = i + 1; j <= r + 1; j++)
{
if (d2 == n + 1)d2 = n - k + 1;
if (a[d2] == dd[j])len++;
d2++;
}
if (len == r + 1 - i)ko++, ans = i;
}
}
if (ko >= 2)cout << "! -1" << endl;
else cout << "! " << ans << " " << n - ans << endl;
}
// if(ok||ko==)cout<<"! -1"<<endl;
}
}
return 0;
}

浙公网安备 33010602011771号