首页 > 其他分享 >Codeforces Round 971 (Div. 4)A~G1

Codeforces Round 971 (Div. 4)A~G1

时间:2024-09-25 22:51:12浏览次数:1  
标签:const cout G1 int ll Codeforces long cin Div

Codeforces Round 971 (Div. 4)A~G1

A. Minimize!

签到不多说。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;

int main()
{
    
  	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    //c-a+b-c = b-a
    int t; cin>>t;
    while(t--)
    {
    	int a,b; cin>>a>>b;
    	cout<<b-a<<"\n";
    }
    return 0;
}

B. osu!mania

签到+1

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 500 + 10;

char a[N][N];

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int t; cin>>t;
    while(t--)
    {
        int n; cin>>n;
        for(int i = 1;i <= n; i++)
            for(int j = 1;j <= 4; j++)
                cin>>a[i][j];

        for(int i = n;i >= 1; i--)
        {
            for(int j = 1;j <= 4; j++)
            {
                if(a[i][j] == '#')
                    cout<<j<<" ";
            }
        }
        cout<<"\n";
    }


    return 0;
}

C. The Legend of Freya the Frog

这边有个小细节,因为总是x方向优先的,所以需要判断一下(类似于黑子先手那样差不多)。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int t; cin>>t;
    while(t--)
    {
        ll x,y,k; cin>>x>>y>>k;
        ll a = x / k + (x % k != 0);
        ll b = y / k + (y % k != 0);
        if(a > b)cout<<a * 2 - 1 <<"\n";
        else cout<<b * 2 <<"\n";
    }
    return 0;
}

D. Satyam and Counting

因为y的范围是[0,1]并且所有点都是整数点,那么问题看起来就简单了。直角三角形只有两种类型了(以y=0为例),一种是在它的正上方有一个点,那么y=1的所有点都可以和这两个点变成直角三角形。第二种就是它的左边和右边刚好都有一个距离为1的点。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
#define int long long
signed main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int t; cin>>t;
    while(t--){
        int n; cin>>n;
        set<int>v0,v1;
        ll ans = 0;
        for(int i = 1;i <= n; i++)
        {
            int x,y; cin>>x>>y;
            if(y == 0) v0.insert(x);
            else v1.insert(x);
        }

        for(auto x : v0)
        {
            // cout<<"x = "<<x<<"\n";
            if(v1.find(x) != v1.end())
                ans += max(0ll,(int)v1.size()-1);
            if(v1.find(x-1) != v1.end() && v1.find(x+1) != v1.end()){
                // cout<<"!!!";
                 ans += 1;
            }
        }

        // cout<<"ans = "<<ans<<"\n";

        for(auto x : v1)
        {
            // cout<<"x = "<<x<<"\n";
            if(v0.find(x) != v0.end())
                ans += max(0ll,(int)v0.size()-1);
            if(v0.find(x-1) != v0.end() && v0.find(x+1) != v0.end()){
                // cout<<"###";
                 ans += 1;
            }
        }

        cout<<ans<<"\n";
    }


    return 0;
}

E. Klee's SUPER DUPER LARGE Array!!!

题意:Klee 有一个长度为 \(n\) 的数组 \(a\),其中包含按顺序排列的整数 $[ k , k + 1 , . . . , k + n − 1 ] $。克利希望选择一个索引 \(i\)( \(i \leq n\) ),使得$ x = |a_1 + a_2 + \dots + a_i - a_{i+1} - \dots - a_n|$ 最小。请注意,对于任意整数 \(z\)而言,$ |z|\(表示\)z$的绝对值。

输出\(x\) 的最小可能值。

直觉就是一半的位置,二分它的左右界,然后两个取min即可。啊注意开long long(因为这个爆了一发)

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;


ll get(ll l,ll r,ll n)
{
    return (l+r)*n/2;
}
int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int t; cin>>t;
    while(t--)
    {
        ll n,k; cin>>n>>k;
        ll s = (k + (k + n - 1)) * n / 2;

        int l = 1,r = n;
        while(l <= r)
        {
            int mid = (l + r)>>1;

            if((k + (k + mid - 1))*mid/2 >= s / 2) r = mid - 1;
            else l = mid + 1;
        }

        ll x = r + 1;
        l = 1,r = n;
        while(l <= r)
        {
            int mid = (l + r)>>1;

            if((k + (k + mid - 1))*mid/2 <= s / 2) l = mid + 1;
            else r = mid - 1;
        }   

        ll y = l - 1;
    
        ll res = min(abs(get(k,k+x-1,x)-get(k+x,k+n-1,n-x)),abs(get(k,k+y-1,y)-get(k+y,k+n-1,n-y)));

        cout<<res<<"\n";

    }


    return 0;
}

正经做法:

证明的话:因为前\(i\)个为正数,后\(n-i\)个为负数。都是等差,两部分求和为\(\dfrac{(2k+i-1)*i}{2}\)和\(\dfrac{(2k+n+i-1)*(n-i)}{2}\)。两个相减就是\(\dfrac{-2kn+4ki-n^2+n+2i^2-2i}{2}\)。是一个单调递增的函数。

那么最趋于0,无非就是最后一个负数和第一个正数取个min。

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;

ll T,n,k;
ll calc(ll i){
	return (-2*k*n+4*k*i-n*n+n+2*i*i-2*i)/2;
}
bool check(ll i){
	return calc(i)>=0;
}

int main(){
	cin>>T;
	while(T--){
		cin>>n>>k;
		ll l=1,r=n;
		while(l<r){
			ll mid=(l+r)>>1;
			if(check(mid))r=mid;
			else l=mid+1;
		}
		cout<<min(abs(calc(l-1)),abs(calc(l)))<<endl;
	}
	return 0;
}

F. Firefly's Queries

题意:
萤火虫是一个给定长度为 \(n\)的数组\(a\)。让 \(c_i\)表示 \(a\) 数组的第$ i$ 次循环移动 。她创建了一个新数组$ b$ ,使得 $b = c_1 + c_2 + \dots + c_n $其中 + 表示连接操作 。

然后,她会向你提出 \(q\) 个查询。对于每一个查询,输出从第 \(l\) 个元素开始,到第 $ r$ 个元素结束的$ b$ 子数组中所有元素的总和,包括两端的元素。

数组 \(a\)的第 \(x\)( $ 1 \leq x \leq n$ ) 次循环移位是\(a_x, a_{x+1} \ldots a_n, a_1, a_2 \ldots a_{x - 1}\)。请注意, 第 $ 1$次移位就是最初的 $ a$。

长度为\(n\) 的两个数组\(p\) 和 \(q\)(换句话说,\(p + q\) )的连接操作是$ p_1, p_2, ..., p_n, q_1, q_2, ..., q_n$。

思路:我们知道对于一个完整的和是固定的。我们可以先求出有多少个循环。然后多出来的部分单独算。

假设对于x位置的循环个数是\(rep=x/n\), 多出来的部分是\(last = x \% n\)。多出来的部分怎么处理呢?我们发现它是一个循环的,不难想到前后缀。如果\(rep + last \le n\)的话直接求就可以了。但是如果\(rep + last > n\)的话,我们就用后面的部分加上前面的部分(相当于是一个前缀一个后缀加起来)。

然后求[l,r]这段的用个简单容斥就可以啦。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e6 + 10;
ll a[N];
ll s[N];
int n,q;
ll cal(ll x)
{
    ll rep = x / n;
    ll res = rep * s[n];
    ll last = x % n;
    // cout<<"s[n]="<<s[n]<<" s[rep] = "<<s[rep]<<" s[last+rep-n] = "<< s[last + rep - n]<<"\n";
    if(last + rep <= n)
        res += s[last + rep] - s[rep];
    else
        res += s[n] - s[rep] + s[last + rep - n];
    return res;

}

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int t; cin>>t;
    while(t--){
        cin>>n>>q;
        for(int i = 1;i <= n; i++)
            cin>>a[i];
        s[0] = 0;
        for(int i = 1;i <= n; i++)
            s[i] = s[i-1] + a[i];
        for(int i = 1;i <= q; i++)
        {
            ll l,r; cin>>l>>r;
            cout<<cal(r)-cal(l-1)<<"\n";
        }
    }

    return 0;
}

G1. Yunli's Subarray Queries (easy version)定长区间连续序列典例

题意:这是问题的简单版本。在这个版本中,可以保证 $ r=l+k-1$ 适用于所有查询。

对于任意数组 \(b\) ,云里可以执行任意多次下面的操作:

选择索引\(i\)。设置\(b_i=x\) ,其中 x 是她想要的任意整数\(( x 不限于区间 [ 1 , n ])\)
将 \(f(b)\) 记为她需要执行的最小操作次数,直到 b 中存在一个长度至少为 k 的连续子数组 。

给云莉一个大小为 \(n\) 的数组 \(a\)并向你提出\(q\)个查询。在每个查询中,你必须输出\(\sum _{j=l+k-1}^{r} f([a_l, a_{l+1}, \ldots, a_j])\)。请注意,在这个版本中,你只需要输出 \(f([a_l, a_{l+1}, \ldots, a_{l+k-1}])\)

如果存在一个从索引 i ( $ 1 \leq i \leq |b|-k+1$ )开始的长度为 \(k\)的连续子数组,那么对于所有的\(i<j\le+k-1\)都是$ b_j = b_{j-1} + 1$

思路:

这个题很有意思也是很典型。一开始想到是长度固定的,有往滑动窗口去想,但是感觉不好实现。我们往本质去思考。转化一下这个题。

对于公差为1的等差(连续),如果我们对每个数加上一个n-i它们就会变成一样的。也就是说,加上之后,如果相等,那么它们在原序列里面是等差。

那么题目就转化为:对于一个\(l\),去找\([l,l+k-1]\)这\(k\)个数里面的众数。而这样的\(l\)最多也就\(n-k+1\)个,果然还是用滑动窗口维护每一个\(l\)的答案就行了。

这个滑动窗口,可以用multiest记录所有元素出现次数的数值集合,然后用map记录某个元素在当前窗口的出现次数。

关键——>定长区间连续序列,想到加上n-i转化为求众数,又因为定长可以用滑动窗口。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;

int n,k,q;
ll a[N],ans[N];
int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int t; cin>>t;
    while(t--)
    {
        cin>>n>>k>>q;
        for(int i = 1;i <= n; i++)
        {
            cin>>a[i];
            ans[i] = 1;
            a[i] += (n-i);
        }
        //可以用multiest记录所有元素出现次数的数值集合
        //然后用map记录某个元素在当前窗口的出现次数。
        multiset<int>all;
        map<int,int>cnt;
        for(int i = 1;i <= n; i++)
        {
            int v = cnt[a[i]]++;
            if(all.find(v) != all.end())
                all.erase(all.find(v));
            all.insert(v + 1);

            if(i >= k){
                ans[i] = *all.rbegin();
                int w = cnt[a[i-k+1]]--;
                all.insert(w - 1);
                if(all.find(w) != all.end())
                    all.erase(all.find(w));
            }   
        }

        while(q--){
            int l,r; cin>>l>>r;
            cout<<k-ans[r]<<"\n";
        }
    }


    return 0;
}

tips(重要!):

  • 因为是定长区间,因此我们可以利用滑动窗口维护定长区间的众数的数量
  • 对于公差为1的等差(连续),如果我们对每个数加上一个n-i它们就会变成一样的。也就是说,加上之后,如果相等,那么它们在原序列里面是等差。

标签:const,cout,G1,int,ll,Codeforces,long,cin,Div
From: https://www.cnblogs.com/nannandbk/p/18432477

相关文章

  • Codeforces Round 974 (Div. 3)题解记录
    A.RobinHelps签到模拟,遍历一遍即可,注意没钱时不给钱。\(O(n)\)#include<iostream>#include<set>#include<map>#include<vector>#include<algorithm>#include<bitset>#include<math.h>#include<string>#include<string.h>#......
  • Codeforces Round 959 (Div. 1 + Div. 2) C. Hungry Games题解
    CodeforcesRound959(Div.1+Div.2)C.HungryGames题解题目链接大致题意:给定一个长度为n的数组,并且给出一对l,r表示一个区间,如果∑i......
  • Codeforces Round 974 (Div.3) 题解
    CodeforcesRound974(Div.3)题解A.RobinHelps模拟按照题意模拟即可。voidShowball(){intn,k;cin>>n>>k;intcur=0,ans=0;for(inti=0;i<n;i++){intx;cin>>x;if(x>=k)cur+=x;elseif(!x){if(cur>=1)cu......
  • codeforces round 974(div.3) D(学会灵活拆分数据)
    解题历程:首先想到的是用数组记录,遍历每一个任务的区间,对区间内的数值加1,比如对于发生在4和8天之内的任务,a[4]++,a[5]++……a[8]++。然后用双指针,记录持续天数的开始下标和结束下标,以l和l+d为边界的窗口遍历每一天,若是最高位寻找任务最多的一天,和区间最大值最小的一天。后来发现......
  • p标签不能嵌套div,h1~h6,p,如果嵌套浏览器会如何解析
    有时候做项目会不小心用p嵌套div,发现控制不了样式,我们放到最后去讲p嵌套div的问题首先,我们先用p标签来嵌套h1~h6,这里我选择h1(h1~h6测试结果都一样),上代码及效果图让我们看下浏览器如何解析我们发现,浏览器把h1标签给单独摘出来了,并且多了个p标签,导致这样的原因:看代码图:首......
  • Codeforces Round 973 (Div. 2)
    A.Zhan'sBlender有\(n\)个水果,每秒可以消耗\(\min\{x,y\}\)个,问需要多少时间。整数除法的上取整操作即可。点击查看代码#include<bits/stdc++.h>usingnamespacestd;#definelllonglong#defineullunsignedlonglongintread(){intx=0;boolf=......
  • Codeforces Round 972(Div.2)题解
    CodeforcesRound972(Div.2)题解A.SimplePalindrome贪心贪心,尽可能元素数量平均,并且相同字母放在一起。#include<bits/stdc++.h>usingnamespacestd;#definefffirst#definesssecond#definepbpush_back#defineall(u)u.begin(),u.end()#defineendl'\n'#de......
  • Codeforces Round 973 (Div.2) A-E题解
    CodeforcesRound973(Div.2)A-E题解比赛传送门A.Zhan'sBlender数学显然答案为\(\lceil\frac{n}{min(x,y)}\rceil\)。#include<bits/stdc++.h>usingnamespacestd;#definefffirst#definesssecond#definepbpush_back#defineall(u)u.begin(),u.en......
  • codeforces 1041 C. Coffee Break
    题意第一行输入三个整数\(n,m,d(1\leqn\leq2*10^5,n\leqm\leq10^9,1\leqd\leqn)\),第二行输入\(n\)个整数,保证每个数均不大于\(m\)。在每一天你都可以任意选择一个未选过的数\(a_i\),随后可以继续选任意一个大于\(a_i+d\)的数\(a_j\);接下来可以再选任意......
  • Codeforces Round 974 (Div. 3)
    CodeforcesRound974(Div.3)A-RobinHelps按题目要求一步步计算就行#include<bits/stdc++.h>usingnamespacestd;intn,k;voidsolve(){ cin>>n>>k; intsum=0,num,ans=0; for(inti=1;i<=n;++i){ cin>>num; if(num&g......