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;
}
posted @ 2025-05-03 13:57  长皆  阅读(118)  评论(0)    收藏  举报