1. 程式人生 > >POI2018

POI2018

Plan metra:

找出 1 1 - n n 的路徑後隨便構造就行了,一開始我想找 d 1

+ d n d_1+d_n 相等的點作為路徑上的點,其實找 d 1 +
d n d_1+d_n
最小的才是正確的,然後還要特判 1 1 n
n
直接相連的情況,這時可以用所有點 d 1 d n |d_1-d_n| 相同來判斷,但是當 d 1 d n |d_1-d_n| 都為 0 0 時, 1 1 n n 不是直接相連的,要特判。

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int Maxn=500010;
const int inf=2147483647;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
int n,mn=inf,lb=0,len=0;
struct Node{int d1,dn,x,id;}a[Maxn],b[Maxn];
bool cmp(Node a,Node b){return a.d1<b.d1;}
struct Edge{int x,y,d;}e[Maxn];
int mark[1000010];
int main()
{
    n=read();bool flag=true;
    if(n==2)return printf("TAK\n1 2 1"),0;
    for(int i=2;i<n;i++)a[i].d1=read(),a[i].id=i;
    for(int i=2;i<n;i++)
    {
        a[i].dn=read();
        a[i].x=a[i].d1-a[i].dn;
        mn=min(mn,a[i].d1+a[i].dn);
        if(i>2&&abs(a[i].x)!=abs(a[i-1].x))flag=false;
    }
    if(flag)
    {
        int dis=abs(a[2].x);
        if(!dis)
        {
            if(n==3)
            {
                puts("TAK");
                printf("%d %d %d\n",1,2,a[2].d1);
                printf("%d %d %d\n",3,2,a[2].d1);
                return 0;
            }
            sort(a+2,a+n,cmp);
            if(a[2].d1==a[3].d1)return puts("NIE"),0;
            puts("TAK");
            printf("%d %d %d\n",1,a[2].id,a[2].d1);
            printf("%d %d %d\n",n,a[2].id,a[2].d1);
            for(int i=3;i<n;i++)printf("%d %d %d\n",a[2].id,a[i].id,a[i].d1-a[2].d1);
            return 0;
        }
        puts("TAK");
        printf("%d %d %d\n",1,n,dis);
        for(int i=2;i<n;i++)
        {
            if(a[i].x>0)printf("%d %d %d\n",i,n,a[i].d1-dis);
            else printf("%d %d %d\n",i,1,a[i].dn-dis);
        }
        return 0;
    }
    else
    {
        memset(mark,-1,sizeof(mark));
        int dis=mn;
        for(int i=2;i<n;i++)
        {
            if(a[i].x==dis)e[++len].x=i,e[len].y=n,e[len].d=a[i].d1-dis;
            else if(a[i].x==-dis)e[++len].x=i,e[len].y=1,e[len].d=a[i].dn-dis;
            else b[++lb]=a[i],b[lb].id=i;
        }
        sort(b+1,b+1+lb,cmp);
        int last=1,lastd=0;
        for(int i=1;i<=lb;i++)
        {
            if(b[i].d1+b[i].dn==dis)
            {
                e[++len].x=last,e[len].y=b[i].id,e[len].d=b[i].d1-lastd;
                if(e[len].d<=0)return puts("NIE"),0;
                last=b[i].id,lastd=b[i].d1;mark[b[i].d1]=b[i].id;
            }
            else
            {
                int d=b[i].d1+b[i].dn-dis;
                if(d&1)return puts("NIE"),0;
                d>>=1;
                if(b[i].d1<=d||mark[b[i].d1-d]==-1)return puts("NIE"),0;
                e[++len].x=mark[b[i].d1-d],e[len].y=b[i].id,e[len].d=d;
            }
        }
        e[++len].x=last,e[len].y=n,e[len].d=dis-lastd;
        if(len!=n-1||e[len].d<=0)return puts("NIE"),0;
        puts("TAK");
        for(int i=1;i<=len;i++)printf("%d %d %d\n",e[i].x,e[i].y,e[i].d);
    }
}

Powódź:

這個題的話抓住如果某個格子的水位高於牆,那麼它周圍的一些格子的水位必須跟它一樣這個性質做,按照牆的高度排序,每次把兩個塊合併,維護合法的答案、高度即可。

程式碼:

#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int Maxn=500010;
const int inf=2147483647;
const int mod=1000000007;
int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
    return x*f;
}
int n,m,H,cnt=0;
int P(int x,int y){return m*(x-1)+y;}
struct Node
{
    int v,type,x,y;
}a[Maxn<<1];
bool cmp(Node a,Node b){return a.v<b.v;}
int Pow(int x,int y)
{
    if(!y)return 1;
    if(y==1)return x;
    int t=Pow(x,y>>1),re=(LL)t*t%mod;
    if(y&1)re=(LL)re*x%mod;
    return re;
}
int fa[Maxn],mx[Maxn],ans[Maxn];
int findfa(int x){return(fa[x]==x?x:fa[x]=findfa(fa[x]));}
void merge(int x,int y,int h)
{
    int fx=findfa(x),fy=findfa(y);
    if(fx!=fy)
    {
        ans[fy]=(LL)(ans[fy]+h-mx[fy])*(ans[fx]+h-mx[fx])%mod;
        mx[fy]=h;
        fa[fx]=fy;
    }
}
int main()
{
    n=read(),m=read(),H=read();
    for(int i=1;i<=n;i++)
    for(int j=1;j<m;j++)
    a[++cnt].v=read(),a[cnt].x=i,a[cnt].y=j,a[cnt].type=0;
    for(int i=1;i<n;i++)
    for(int j=1;j<=m;j++)
    a[++cnt].v=read(),a[cnt].x=i,a[cnt].y=j,a[cnt].type=1;
    sort(a+1,a+1+cnt,cmp);
    for(int i=1;i<=n*m;i++)fa[i]=i,mx[i]=-1,ans[i]=0;
    for(