Codeforces Round #535 (Div. 3)

E:

题意:

给出n个整数ai和m个区间[li,ri] 你可以选择一些区间,并且将区间内的数字都减一。你要选择一些区间,然后使得改变后的数列中maxbi-minbi的值最大。

题解:

假设我们已经知道了这n个数中最大值的位置pmax,和最小值的位置pmin,那么对于一个区间[li,ri],有三种情况。

1.如果pmax和pmin在区间[li,ri]内,那么这个区间加不加都对答案没有贡献。

2.如果pmin在区间内pmax不在区间内,那么这个区间加上对答案的贡献就为1

3.如果pmax在区间内pmin不在区间内,那么加上这个区间对答案的贡献为-1.

所以我们发现,只要pmin在区间内的区间,选上它答案一定不会变的更差。

那么n*m的复杂度就可以解决这个问题了,将区间按照左区间排序,从1到n扫,当前i为某个区间的开始或者结束点的时候,更新和消除影响。

F:

题意:

给出n个点和m条边,没有重边和自环。问你最少要给多少条边的权值+1使得MST不变且唯一。

题解:

我们定义一下冲突边:存在一些边,权值都是当前都小的,且只能从这里面选一条边加入MST,即,原本他们都能加入MST,但是加入一条以后剩余的都没法加入MST了。

对于所有的冲突边,选一条加入MST,然后其他边的权值都要+1.

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5
 6 using namespace std;
 7 const int maxn=2e5+10;
 8 struct Edge{
 9     int from,to,w;
10     bool operator<(const Edge& rhs)const{
11         return w<rhs.w;
12     }
13 }edges[maxn];
14 int n,m;
15 int p[maxn];
16 int find(int x){
17     return p[x]==x?x:p[x]=find(p[x]);
18 }
19
20 int main(){
21     scanf("%d%d",&n,&m);
22     for(int i=1;i<=n;i++)p[i]=i;
23     for(int i=1;i<=m;i++)
24         scanf("%d%d%d",&edges[i].from,&edges[i].to,&edges[i].w);
25     sort(edges+1,edges+1+m);
26     int ans=0;
27     for(int i=1;i<=m;){
28         int j=i;
29         while(edges[j].w==edges[i].w){
30             j++;
31         }
32         j--;
33         int num=0;
34         for(int k=i;k<=j;k++){
35             int x=find(edges[k].from);
36             int y=find(edges[k].to);
37             if(x!=y)
38                 num++;
39         }
40         for(int k=i;k<=j;k++){
41             int x=find(edges[k].from);
42             int y=find(edges[k].to);
43             if(x!=y){
44                 p[x]=y;
45                 num--;
46             }
47         }
48         ans+=num;
49         i=j+1;
50     }
51     printf("%d\n",ans);
52 return 0;
53 }

原文地址:https://www.cnblogs.com/LQLlulu/p/10385390.html

时间: 2024-10-07 02:29:20

Codeforces Round #535 (Div. 3)的相关文章

Codeforces Round #535 (Div. 3)小上分记

Codeforces Round #535 (Div. 3)小上分记 前言 被拉去买新年衣服了,导致半小时后才进场. 虽然做了4道题,但是rating还是涨得不多. 用predictor看了rating变化后心灰意冷,不看E题了. A ...800的难度. B 本来还在想要不要用什么STL.后来发现直接用桶就行了.然后就可以水过了. C 题意差点理解不了. 就6种情况都去考虑一下,找最小代价的即可.不要考虑少了. 每次都是\(O(n)\)的,所以能搞. D 贪心地换字母即可. E 坑.待填. 原

B类-Codeforces Round #535 (Div. 3)C. Nice Garland

Codeforces Round #535 (Div. 3)C. Nice Garland 题意: 由'R', 'G' and 'B' 三个字母组成的一个字符串,每两个相同的字母需要相差3,找出最小需要交换次数. 分析: 这个字符串的长度大于等于3的时候,一定是RBG这三个字符的某一个排列的循环.RBG一共最多有6种排列方式{"RGB","RBG","BGR","BRG","GRB","GBR&q

Codeforces Round #535 (Div. 3) 题解

Codeforces Round #535 (Div. 3) 题目总链接:https://codeforces.com/contest/1108 太懒了啊~好久之前的我现在才更新,赶紧补上吧,不能漏掉了. A. Two distinct points 题意: 给出两个区间的左右边界,输出两个数,满足两个数分别在两个区间内且这两个数不相等. 题解: 直接输出左端点然后判断一下就行了. 代码如下: #include <bits/stdc++.h> using namespace std; type

Codeforces Round #535 (Div. 3) F

F. MST Unification 题目传送门 题意: 给你n个顶点,m条边:保证没有重边,其中存在多个MST(最小生成树), 你可以修改一些边的权值,让其中有且仅有一个最小生成树,求最少操作的边数. 思路: 最小生成树算法的加工,我们从kruskal算法入手,kruskal就是先对边排序, 然后遍历边不断加入一些合格边来完善最小生成树 那么在这个过程中,如果边的权值一样的话,就会产生多种MST,但是这里 不能仅仅只是累计相同权值的边数,因为与合格边相同权值的边可能可以选择 多条. 所以我们可

Codeforces Round #535 (Div. 3) 1108C - Nice Garland

#include <bits/stdc++.h> using namespace std; int main() { #ifdef _DEBUG freopen("input.txt", "r", stdin); // freopen("output.txt", "w", stdout); #endif int n; string s; cin >> n >> s; vector<in

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿

Codeforces Round #424 (Div. 2) C. Jury Marks(乱搞)

题目链接:Codeforces Round #424 (Div. 2) C. Jury Marks 题意: 给你一个有n个数序列,现在让你确定一个x,使得x通过挨着加这个序列的每一个数能出现所有给出的k个数. 问合法的x有多少个.题目保证这k个数完全不同. 题解: 显然,要将这n个数求一下前缀和,并且排一下序,这样,能出现的数就可以表示为x+a,x+b,x+c了. 这里 x+a,x+b,x+c是递增的.这里我把这个序列叫做A序列 然后对于给出的k个数,我们也排一下序,这里我把它叫做B序列,如果我

[Codeforces] Round #352 (Div. 2)

人生不止眼前的狗血,还有远方的狗带 A题B题一如既往的丝帛题 A题题意:询问按照12345678910111213...的顺序排列下去第n(n<=10^3)个数是多少 题解:打表,输出 1 #include<bits/stdc++.h> 2 using namespace std; 3 int dig[10],A[1005]; 4 int main(){ 5 int aa=0; 6 for(int i=1;;i++){ 7 int x=i,dd=0; 8 while(x)dig[++dd