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