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 }
View Code

 

posted @ 2019-02-15 18:47  蒟蒻LQL  阅读(187)  评论(0编辑  收藏  举报