1. 程式人生 > 其它 >Codeforces Problem/1619/G題解

Codeforces Problem/1619/G題解

這次用中文。

傳送門:https://codeforces.com/problemset/problem/1619/G

一開始的思路是用LCT做,簡單明瞭。一個點如果能夠引爆另一個點,那麼另一個點也一定能夠引爆它,所以只要讓它們的父親節點是能夠引爆它們並且能夠被它們引爆的節點的耗時最少的那一個即可。之後每秒都從還沒引爆的點中耗時最多的那個開始引爆,直至到某一時刻剩下的所有點都自己爆炸為止即可。下面的程式碼在T4被TLE了。想想也對,畢竟我這樣找LCT嚴格意義上是O(n2)的演算法,被卡很正常。

#include<bits/stdc++.h>
using namespace std;
#define N 200005
#define mp make_pair
#define ll long long
int tt;
int n;
int k;
int x[N];
int y[N];
int t[N];
int fa[N];
int find(int k) {
    if(fa[k]==k) return k;
    else {
        fa[k] = find(fa[k]);
        return fa[k];
    }
}
bool vis[N];
int main() {
    cin>>tt;
    while(tt--) {
        cin>>n>>k;
        for(int i=1; i<=n; i++) fa[i] = i;
        for(int i=1; i<=n; i++) {
            cin>>x[i]>>y[i]>>t[i];
            bool flag = false;
            for(int j=1; j<i; j++) vis[j] = false;
            for(int j=1; j<i; j++) {
                if((x[i]==x[j]&&abs(y[i]-y[j])<=k)||(y[i]==y[j]&&abs(x[i]-x[j])<=k)) {
                    if(vis[find(j)]) continue;
                    else{
                        if(t[find(i)]<t[find(j)]) {
                            fa[find(j)] = find(i);
                        } else fa[find(i)] = find(j);
                        vis[find(j)] = true;
                    }
                }
            }
//            cout<<"fa[i] = "<<fa[i]<<endl;
        }
        priority_queue<int> q;
        for(int i=1; i<=n; i++) if(find(i)==i) q.push(t[i]);
        int now = -1;
        while(!q.empty()) {
            int t1 = q.top();
            q.pop();
            if(t1<=now) break;
            now++;
        }
        cout<<now<<endl;
    }
    return 0;
}

  

那麼這道題的問題就在於如何優化LCT。需要注意的是一個點只能引爆與它在同一橫軸或是用以豎軸上的點。如果先按照橫軸、豎軸排序,時間複雜度雖然不會優化(這種方法當所有點都在同一軸上時比較次數還是會退化為一開始的比較次數的),但是普通的情況確實更優,可以一試。嘗試後,這種方法過了,但耗時仍在1091ms。

上述的優化在於排序完之後一個點只要向後看到和它橫縱座標不一致的點時就可以停止,而不必每一個都計算。

ACcode:

#include<bits/stdc++.h>
using namespace std;
#define N 200005
#define mp make_pair
#define
ll long long int tt; int n; int k; int x[N]; int y[N]; int t[N]; int fa[N]; int find(int k) { if(fa[k]==k) return k; else { fa[k] = find(fa[k]); return fa[k]; } } bool vis[N]; int main() { cin>>tt; while(tt--) { cin>>n>>k; vector
<pair<int,int>> vec; for(int i=1; i<=n; i++) fa[i] = i; for(int i=1; i<=n; i++) { cin>>x[i]>>y[i]>>t[i]; vec.push_back(mp(x[i],i)); } sort(vec.begin(),vec.end()); for(int i=0; i<n; i++) { for(int j = i+1; j<n; j++) { if(vec[i].first!=vec[j].first) break; int noi = vec[i].second; int noj = vec[j].second; if(abs(y[noi]-y[noj])<=k) { if(t[find(noi)]<t[find(noj)]) { fa[find(noj)] = find(noi); } else fa[find(noi)] = find(noj); } } } vec.clear(); for(int i=1; i<=n; i++) vec.push_back(mp(y[i],i)); sort(vec.begin(),vec.end()); for(int i=0; i<n; i++) { for(int j = i+1; j<n; j++) { if(vec[i].first!=vec[j].first) break; int noi = vec[i].second; int noj = vec[j].second; if(abs(x[noi]-x[noj])<=k) { if(t[find(noi)]<t[find(noj)]) { fa[find(noj)] = find(noi); } else fa[find(noi)] = find(noj); } } } priority_queue<int> q; for(int i=1; i<=n; i++) if(find(i)==i) q.push(t[i]); int now = -1; while(!q.empty()) { int t1 = q.top(); q.pop(); if(t1<=now) break; now++; } cout<<now<<endl; } return 0; }