1. 程式人生 > >BZOJ 2139 road

BZOJ 2139 road

所有 https 比較 clas space stdin putchar efi www.

目錄

  • 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%10+'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;
}

BZOJ 2139 road