[ONTAK2010]Peaks

题目大意:
  一个图上有$n(n\leq100000)$个带权点,$m(m\leq500000)$条带权边。有$q(q\leq500000)$组询问,每次询问从点$v$出发,只经过权值小于等于$x$的边能到达的点中,权值第$k$大的点权。

思路:
  离线处理每个询问。将询问和边分别按权值排序,处理到当前询问时,将权值小于等于$x$的边加入到图中。用权值线段树维护每个连通块的权值。点的联通情况用并查集维护(相当于Kruskal),权值线段树直接合并。时间复杂度$O(n\log n+m\log m+q\log q+q\log n)$。

  1 #include<cstdio>
  2 #include<cctype>
  3 #include<algorithm>
  4 inline int getint() {
  5     register char ch;
  6     while(!isdigit(ch=getchar()));
  7     register int x=ch^'0';
  8     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
  9     return x;
 10 }
 11 const int N=100001,M=500000,Q=500000;
 12 int h[N],tmp[N],ans[Q];
 13 struct Edge {
 14     int u,v,w;
 15     bool operator < (const Edge &another) const {
 16         return w<another.w;
 17     }
 18 };
 19 Edge e[M];
 20 struct Query {
 21     int v,x,k,id;
 22     bool operator < (const Query &another) const {
 23         return x<another.x;
 24     }
 25 };
 26 Query q[Q];
 27 struct DisjointSet {
 28     int anc[N];
 29     int find(const int &x) {
 30         return x==anc[x]?x:anc[x]=find(anc[x]);
 31     }
 32     void reset(const int &n) {
 33         for(register int i=1;i<=n;i++) anc[i]=i;
 34     }
 35     void merge(const int &x,const int &y) {
 36         anc[find(y)]=find(x);
 37     }
 38     bool same(const int &x,const int &y) {
 39         return find(x)==find(y);
 40     }
 41 };
 42 DisjointSet s;
 43 class SegmentTree {
 44     private:
 45         struct Node {
 46             int val;
 47             Node *left,*right;
 48             Node(const int &v):val(v),left(NULL),right(NULL) {}
 49         };
 50         void modify(Node *&p,const int &b,const int &e,const int &x) {
 51             p=new Node(1);
 52             if(b==e) return;
 53             const int mid=(b+e)>>1;
 54             if(x<=mid) modify(p->left,b,mid,x);
 55             if(x>mid) modify(p->right,mid+1,e,x);
 56         }
 57     public:
 58         Node *root[N];
 59         void reset(const int &n) {
 60             for(register int i=1;i<=n;i++) {
 61                 modify(root[i],1,tmp[0],h[i]);
 62             }
 63         }
 64         void merge(Node *&p1,Node *const &p2) {
 65             if(!p1) {
 66                 p1=p2;
 67                 return;
 68             }
 69             if(!p2) return;
 70             p1->val+=p2->val;
 71             merge(p1->left,p2->left);
 72             merge(p1->right,p2->right);
 73             delete p2;
 74         }
 75         int query(const Node *const &p,const int &b,const int &e,const int &k) const {
 76             if(p->val<k) return -1;
 77             if(b==e) return b;
 78             const int mid=(b+e)>>1;
 79             if(!p->right) return query(p->left,b,mid,k);
 80             if(k<=p->right->val) return query(p->right,mid+1,e,k);
 81             return query(p->left,b,mid,k-p->right->val);
 82         }
 83 };
 84 SegmentTree t;
 85 inline void add_edge(const Edge &e) {
 86     if(s.same(e.u,e.v)) return;
 87     t.merge(t.root[s.find(e.u)],t.root[s.find(e.v)]);
 88     s.merge(e.u,e.v);
 89 }
 90 int main() {
 91     const int n=getint(),m=getint(),cnt_q=getint();
 92     for(register int i=1;i<=n;i++) {
 93         tmp[i]=h[i]=getint();
 94     }
 95     std::sort(&tmp[1],&tmp[n]+1);
 96     tmp[0]=std::unique(&tmp[1],&tmp[n]+1)-&tmp[1];
 97     for(register int i=1;i<=n;i++) {
 98         h[i]=std::lower_bound(&tmp[1],&tmp[tmp[0]]+1,h[i])-&tmp[0];
 99     }
100     for(register int i=0;i<m;i++) {
101         const int u=getint(),v=getint(),w=getint();
102         e[i]=(Edge){u,v,w};
103     }
104     std::sort(&e[0],&e[m]);
105     for(register int i=0;i<cnt_q;i++) {
106         const int v=getint(),x=getint(),k=getint();
107         q[i]=(Query){v,x,k,i};
108     }
109     std::sort(&q[0],&q[cnt_q]);
110     s.reset(n);
111     t.reset(n);
112     for(register int i=0,p=0;i<cnt_q;i++) {
113         while(p<m&&e[p].w<=q[i].x) add_edge(e[p++]);
114         ans[q[i].id]=t.query(t.root[s.find(q[i].v)],1,tmp[0],q[i].k);
115     }
116     for(register int i=0;i<cnt_q;i++) {
117         printf("%d\n",~ans[i]?tmp[ans[i]]:-1);
118     }
119     return 0;
120 }

 

posted @ 2018-02-23 09:43  skylee03  阅读(112)  评论(0编辑  收藏  举报