2017上海市高校程序設計邀請賽_D

problem list
D 蘿莉理論計算機科學家

這裏寫圖片描述

  • 有點噁心,第一感覺是線段樹的一定是走火入魔了(比如我)
  • 實際上是差分約束,可以用dfs或並查集來做,並查集不能壓縮路徑
  • 並查集更藝術些效率更高些~
  • g[x]表示從節點x到根節點的路徑上的數值總和(當做向量來理解)
  • c[x]表示從節點x到鄰近父節點的數值
  • g[x] = c[x] + g[fx] ;
  • 這裏寫圖片描述
  • c[fy] = g[x] + w - g[y];
  • 差分約束也是在向量計算這裏體現出來的
  • 判定矛盾的條件則是當兩個端點的根節點一致時
  • 這裏寫圖片描述
  • g[y]-g[x] != w[i] -> ans=0
  • 看數據量知道要離散化處理
  • 還要注意的是題目裏講的是每個節點都是有數值的,數據代指一段節點總和的值 [u,v]==w。實際上如果把節點的值當做木板長度,第u到第v個木板總長是w就不難理解,這裏在實際計算過程中要v[i]++或u[i]–,總是要對節點區間增1,就和線段樹裏面對於連續區間維護的操作一個道理。(這個最容易忽略,很容易漏掉。要是前面的都完成的很好,這裏出錯以至於全盤重做就很僵硬)
  • 恩,要感謝LCJ,我倆一起商量完善的思路,之後我給實現了下下~
#include <bits/stdc++.h>
using namespace std;
typedef long long           LL ;
typedef unsigned long long ULL ;
const int    maxn = 100000 + 10;
const int    inf  = 0x3f3f3f3f ;
const int    npos = -1         ;
const double eps  = 1e-20      ;

int m, n, ans;
int u[maxn<<1], v[maxn<<1], num[maxn<<1], f[maxn<<1];
LL w[maxn<<1], c[maxn<<1], g[maxn<<1];
std::map< int, int > mp;
int Find(int x){
    int f1=f[x], f2=x;
    if(f1!=f2){
        f2=Find(f1);
    }
    g[x]=c[x]+g[f1];
    return f2;
}
void Union(int x, int fx, int y, int fy, LL z){
    f[fy]=fx;
    c[fy]=g[x]+z-g[y];
}
int main(){
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    while(~scanf("%d",&m)){
        ans=1;
        n=0;
        mp.clear();
        for(int i=1;i<=m;i++){
            scanf("%d %d %lld",&u[i],&v[i],&w[i]);
            v[i]++;
            if(!mp.count(u[i]))
                {mp.insert(make_pair(u[i],1));num[++n]=u[i];}
            if(!mp.count(v[i]))
                {mp.insert(make_pair(v[i],1));num[++n]=v[i];}
        }
        sort(num+1,num+1+n);
        for(int i=1;i<=n;i++){
            f[i]=i;
            g[i]=0;
            c[i]=0;
        }
        for(int i=1;i<=m;i++){
            int x=lower_bound(num+1,num+1+n,u[i])-num;
            int y=lower_bound(num+1,num+1+n,v[i])-num;
            int fx=Find(x), fy=Find(y);
            if(fx==fy){
                if(g[y]-g[x]!=w[i]){
                    ans=0;
                    break;
                }
            }else{
                Union(x,fx,y,fy,w[i]);
            }
        }
        puts(ans?"2333!(=v=)":"666~~~(=_=)");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章