首页 > 其他分享 >Codeforces Round #816 (Div. 2)

Codeforces Round #816 (Div. 2)

时间:2022-12-02 18:11:52浏览次数:62  
标签:std int LL Codeforces long Div include 我们 816

[比赛链接](Dashboard - Codeforces Round #816 (Div. 2) - Codeforces)

B

题意:给定数组长度n,参数k,\(\sum_{1}^{n}a_i/k=b\),并且区间和是s。其中b和s都是题目给定的。

核心思路:这题我们可以抽象为一个被杯子倒水模型,就是我们先把所有的水,也就是s导入一个被子里面,如果s/k小于b,那么就肯定无解。因为我们接下来只有可能往每个被子里面导入k-1的水,使得这个值变小。因为\(\frac{k-1}{k}=0\).所以我们碰到问题得想考虑无解的情况。才好进一步思考。

但是我们要注意我们刚开始的s,可能减去k-1,它可以被整除,所以整体的值可能加1,就比如:10/3=3 9/3=3;

其实就是我们的第一杯水,随之值减小,可不可以被k-1整除的问题。下面的代码的地方很精髓。

接下来就可以直接上代码了

#include<bits/stdc++.h>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N = 200010;
int a[N];
void solve() {
    int n, k, b;
    LL s;
    std::cin >> n >> k >> b >> s;

    LL cur = s / k;
    if (b > cur) {
        std::cout << "-1\n";
        return;
    }

    std::vector<LL> a(n);
    a[0] = s;

    for (int i = 1; i < n; i++) {
        if (cur > b && a[0] >= k) {
            cur -= (a[0] % k != k - 1);
            a[0] -= k - 1;
            a[i] = k - 1;
        }
    }

    if (cur != b) {
        std::cout << "-1\n";
        return;
    }
    for (int i = 0; i < n; i++) {
        std::cout << a[i] << " \n"[i == n - 1];
    }
}
int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		solve();
	}
}

C

题意:就是一个公式,不太好解释。

核心思路

  1. 首先我们需要把整个数组对应的值求出来,这个怎么求呢。就是我们可以从前往后地推。假设我们插入的a[i]!=a[i-1],那就说明所有包含a[i]的区间,他们的一个贡献值也就是区间的价值都会加一,而我们的区间数目就是区间中点的数目,这个自己模拟下就懂了,所以总体价值加i.但是如果相等,那么就只能加1,就是加上a[i]自己的长度。

  2. 接下来就只考虑把a[x]改为y的影响,很显然我们只需要比较a[x-1],a[x+1]与y的一个关系。下面来推导其中一种情况,如果刚开始i和i-1不相等,改完之后相等了,那么总体价值需要减去包含了a[x]的区间,这里一定要注意我们刚开始的总价值的推导。左边包含x的点:n-x+1,右边包含:x+1.接下来使用乘法原理就好了。i与i+1也是这么分析的。

这个题目我们可以多画图,某个区间包含某个点,我们可以以这个点为中心,向右或者向左延申一定长度的线段。

#include<bits/stdc++.h>
#include<unordered_map>
#define IOS std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;
typedef long long LL;
const int N = 2e5+10;
LL inf = (1LL << 30)-1 ;
typedef pair<int, int> PII;
LL a[N];
LL n, m;
void solve()
{
	cin >> n >> m;
	for (int i = 1;i <= n;i++)
		cin >> a[i];
	a[0] = -1, a[n+1] = -1;//这个只是单纯的为了放着相等的,因为a[i]都是大于0数
	LL ans = 1, suf = 1;//这是a[1]的贡献,所下面我们从i=2开始枚举,suf表示加入i的贡献
	for (int i = 2;i <= n;i++)
	{
		if (a[i] != a[i - 1])
		{
			suf += i;
			ans += suf;
		}
		else
		{
			suf += 1;
			ans += suf;
		}
	}
	while (m--)
	{
		LL x, y;
		cin >> x >> y;
		if (a[x] == y)
		{
			cout << ans << endl;
			continue;
		}
		if (y == a[x - 1] && a[x] != a[x - 1])
			ans -= (n - x + 1)*(x - 1);
		if (y != a[x - 1] && a[x] == a[x - 1])
			ans += (n - x + 1) * (x - 1);
		if (y == a[x+1] && a[x] != a[x + 1])
			ans -= (n - x) * (x);
		if (y != a[x+1] && a[x] == a[x + 1])
			ans += (n - x) * x;
		cout << ans << endl;
		a[x] = y;//因为后面也需要用
	}
}
int main()
{
	solve();
}

D

题意:给定数组长度,再给定m个关系,每个关系保证给定x, y, v,使得a[x] | a[y] = v。求该数组的最小字典序。

核心思路:首先我们可以知道这个方程必然是有解的,然后考虑一些或操作的性质。就是如果v上的二进制某个位置是0,那么a[x]与a[y]也是。所以我们整个题目需要按位考虑

然后我们注意a[x]可能或不同的a[y]等于不同的v,所以这个题目我们可以考虑建立一个图,点是a[x],a[y].边权是x。

然后我们注意题目要求最小字典序,所以我们先把每个a[i]的每一个二进制位置都放1.然后根据a[j]和v的情况放0。我们从1-n进行一个贪心,就是高位到低位进行贪心的放0。、

下面这是一个简单的图:

#include<bits/stdc++.h>
#include<unordered_map>
#define IOS std::ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
using namespace std;
typedef long long LL;
const int N = 2e5+10;
LL inf = (1LL << 30)-1 ;
typedef pair<int, int> PII;
int a[N],vis[N];
int n, q;
void slove() {
    cin >> n >> q;
    vector<vector<PII>> g(N);   
    for (int i = 1; i <= n; i++)a[i] = (1 << 30) - 1;
    while (q--) {
        int i, j, x; cin >> i >> j >> x;
        if (i == j) {
            vis[i] = 1;
            a[i] = x;
        }
        else {
            g[i].push_back({ j,x });
            g[j].push_back({ i,x });
            for (int k = 0; k <= 29; k++)if ((x >> k & 1) == 0) {
                if (a[i] >> k & 1)a[i] ^= (1 << k);
                if (a[j] >> k & 1)a[j] ^= (1 << k);
            }
        }
    }
    for (int k = 29; k >= 0; k--) {
        for (int i = 1; i <= n; i++) {
            if (vis[i])continue;
            if ((a[i] >> k & 1) == 0)continue;
            //a[i]  在第k位上是1 ,我们看看他能不能变成0
            bool flag = 1;
            for (auto p : g[i]) {
                int j = p.first, x = p.second;
                if ((x >> k & 1) == 0)continue;//只要 第k位上为 1的边
                if ((a[j] >> k & 1) == 0)flag = 0;
            }
            if (flag)a[i] ^= (1 << k);
        }
    }
    for (int i = 1; i <= n; i++)cout << a[i] << " ";
    cout << endl;
}
int main()
{
    slove();
}

这次的div2的c有点难,想了比较久。

标签:std,int,LL,Codeforces,long,Div,include,我们,816
From: https://www.cnblogs.com/xyh-hnust666/p/16945258.html

相关文章

  • CodeForces - 476C-Dreamoon and Sums(数学思维)
    C.DreamoonandSums题解:设则有题目所求可得所以代码#include<bits/stdc++.h>typedeflonglongLL;usingnamespacestd;constintmod=1e9+7;intmain(){#ifndefO......
  • Pinely Round 1 (Div. 1 + Div. 2)(持续更新)
    Preface其实这场上周一就补了ABC,但是由于各种事情的堆积一直到今天才开始接着补D再不写博客的话可能题意都要忘光光了,赶紧来Rush一发A.TwoPermutations简单观察发现......
  • 29. Divide Two Integers
    Dividetwointegerswithoutusingmultiplication,divisionandmodoperator.Ifitisoverflow,returnMAX_INT.那么如果每次不仅仅减去1个除数,计算速度就会增加,但......
  • Codeforces Global Round 10 H. ZS Shuffles Cards
    题目链接设f[i]表示还有i个数不在集合内的期望步数,尝试列一下转移式,会发现式子由转移到下一轮的期望步数和之后的DP值组成,考虑DP的转移过程,就会发现答案为转移到下一轮的......
  • 世界杯火热进行中, 用一个div画个足球场助助兴
    四年一度的世界杯正在火热进行中,有没有熬夜看你喜欢的队伍比赛呢。在这欢庆的氛围中,我决定用代码参与一把世界杯,擦边参与,那就是用CSS画一个足球场,正常的用CSS布局肯定是非常......
  • 实现div元素滚动条默认滚动到最底部 - 使用场景 - 聊天信息框
    实现div元素滚动条默认滚动到最底端使用场景:聊天信息框需要了解几个属性和方法:scrollHeight:元素高度-包含滚动条隐藏部分clientHeight:元素可视高度-不包含滚动条隐......
  • Codeforces Round #154(Div.2)
    C.TextEditor【题意】有一篇文章,包含\(i\)行,每行有\(a_i\)个字母,也就是\(a_i+1\)个放置光标的位置。对于一个位于\((x,y)\)光标,每次操作可以上移/下移/左移/......
  • Math: GCD greatest common divisor 最大公约数
     Loop:#include<stdio.h>intmain(void){printf("Hello,World!\n");intm,n,r;scanf("%d%d",&m,&n);if(m<n){m=m^n;......
  • CSS怎么解决图片过大撑破DIV网页的问题?
    一、防止图片撑破DIV方法——缩小图片尺寸原始处理方法是将要展示的图片进行处理。比如你的DIV宽度为500px(像素),那你上传的图片或放入网页的图片宽度就要小于500px,也就是......
  • Codeforces Global Round 21 E
    E.PlacingJinas题链稍微手写一下发现就是一个杨辉三角然后我们知道杨辉三角第n行第m个是C(m-1,n-1)我们对应转化过来就是C(n+m-2,m-1)然后我们注意处理的组合数到4e5因......