zoukankan      html  css  js  c++  java
  • BZOJ 2139 road

    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%10+'0');}
    template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('
    ');}
    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
    ",ans);
    	return 0;
    }
    
    「我不敢下苦功琢磨自己,怕终于知道自己并非珠玉;然而心中既存着一丝希冀,便又不肯甘心与瓦砾为伍。」
  • 相关阅读:
    区块链技术栈-区块链账本
    (引文)可扩展的分布式数据库架构
    CentOS7 通过systemd 添加开机重启服务
    spring发布RMI服务(-)
    使用jdbc连接上oracle的两种方法
    用户态和内核态
    MySQL数据库备份还原(基于binlog的增量备份)
    分布式事务
    shuffle 过程
    MapReduce的流程
  • 原文地址:https://www.cnblogs.com/Apocrypha/p/9574196.html
Copyright © 2011-2022 走看看