1. 程式人生 > 實用技巧 >ACL Contest 1

ACL Contest 1

A - Reachable Towns
參考了題解:單調棧+並查集
這題一開始用的是O(n^2)列舉+並查集,T掉了
做法:
對原序列的第一維座標升序排序,維護一個以第二維座標為參照的單調不增的單調棧,棧中存放(pos, y)二元組,這個表示城市pos所在的集合中最小的y座標。

#include<iostream>
#include<algorithm>

using namespace std;

#define PII pair<int, int>

const int N = 200010, INF = 0x3f3f3f3f;

typedef struct{
    int x, y, pos;
}state;

state a[N];
int cnt[N], p[N];
int n;
PII stk[N];
int tt = -1;

int cmp(const state &a, const state &b){
    return a.x < b.x;
}

int find(int x){
    if(x != p[x]) p[x] = find(p[x]);
    return p[x];
}

int main(){
    cin >> n;
    
    for(int i = 0; i < n; i ++){
        int x, y;
        cin >> x >> y;
        
        a[i] = {x, y, i};
    }
    
    for(int i = 0; i < n; i ++) p[i] = i, cnt[i] = 1;
    
    sort(a, a + n, cmp);
    
    for(int i = 0; i < n; i ++){
        if(tt == -1) stk[++ tt] = {a[i].pos, a[i].y};
        else{
            int minv = a[i].y;
            while(~tt && a[i].y > stk[tt].second){
                minv = min(minv, stk[tt].second);
                int x = find(a[i].pos), y = find(stk[tt].first);
                if(x != y){
                    p[x] = y;
                    cnt[y] += cnt[x];
                }
                tt --;
            }
            stk[++ tt] = {a[i].pos, minv};
        }
    }
    
    for(int i = 0; i < n; i ++) cout << cnt[find(i)] << endl;
    
    return 0;
}

剩下的題。。。慢慢補吧。
123