BZOJ 2139 road

mac2022-06-30  126

目录

BZOJ 2139 road题意题解Code

BZOJ 2139 road

题目传送门1

题意

很久很久以前,中原地区分成了N个国家,编号为1到N,任意两个国家都可互达。每个国家有一个攻击值\(A[i]\)和防御值\(B[i]\)。定义一个人从i国去j国的危险值为:假如\(A[i]>B[j]\),则危险值为\(( A[i]^2-B[j]^2)\),否则危险值为0。现在,Nan从国家1出发,经过每一个国家有且仅有一次,最后回到国家1,要求找出一种方案,使得其中危险值的最大值最小。

题解

感觉网上的题解好少啊,实际上想通了似乎发现这题还是比较的好写的,不过仍然还是一道十分妙妙的题目。在看到我们现将所有国家的\(a\)\(b\)开来,然后我们分别按他们的值从小到大排序,然后先贪心的进行连边。这个时候,我们的连边方式一定是从\(a_i\)属于的那个国家连向\(b_i\)属于的那个国家,因为这样可以保证连出来的边危险值的最大值最小(这个可以意会一下)。这样我们就会得到许多小环,然后我们的目的就是把这些小环连成一个大环。所以我们考虑在这些环上加边,由于我们还要保证环之间的边能够尽量的小,所以我们在环之间的边一定是从\(a_i\)属于的那个国家连向\(b_{i-1}\)属于的那个国家(因为如果连向\(b_{i+1}\)所属的国家的话,那么\(a_n\)连向的国家一定是\(b_1\)所属的国家,那样就没有之前那种方案连那么优了)知道这个之后我们就可以对这些环做最小生成树了,每次连边的时候更新一下答案就行了,复杂度为\(O(nlogn)\)

Code

#include <bits/stdc++.h> using namespace std; typedef long long ll; bool Finish_read; template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;} template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x+'0');} template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');} template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);} /*================Header Template==============*/ #define PAUSE printf("Press Enter key to continue..."); fgetc(stdin); const int N=1e6+500; const int Md=32767; struct country { int idx,v; bool operator < (const country &rhs) const { return v<rhs.v; } }a[N],b[N],c[N]; int n,x,y,z; int fa[N]; int ans; /*==================Define Area================*/ int Find(int x) {return fa[x]==x?x:fa[x]=Find(fa[x]);} int Sqr(int x) {return x*x;} int main() { read(n); read(a[1].v);read(a[2].v);read(x);read(y);read(z); for(int i=3;i<=n;i++) a[i].v=((ll)x*a[i-1].v+(ll)y*a[i-2].v+z)%Md; read(b[1].v);read(b[2].v);read(x);read(y);read(z); for(int i=3;i<=n;i++) b[i].v=((ll)x*b[i-1].v+(ll)y*b[i-2].v+z)%Md; for(int i=1;i<=n;i++) fa[i]=a[i].idx=b[i].idx=i; sort(a+1,a+1+n);sort(b+1,b+1+n); for(int i=1;i<=n;i++) { ans=max(ans,Sqr(a[i].v)-Sqr(b[i].v)); fa[Find(a[i].idx)]=Find(b[i].idx); } for(int i=2;i<=n;i++) { c[i].v=Sqr(a[i].v)-Sqr(b[i-1].v);c[i].idx=i; } sort(c+1,c+n); for(int i=1;i<n;i++) { int fx=Find(a[c[i].idx].idx),fy=Find(b[c[i].idx-1].idx); if(fx!=fy) ans=max(ans,c[i].v),fa[fx]=fy; } printf("%d\n",ans); return 0; }

转载于:https://www.cnblogs.com/Apocrypha/p/9574196.html

最新回复(0)