• 【线段树合并】bzoj3545: [ONTAK2010]Peaks


    1A还行

    Description

    在Bytemountains有N座山峰,每座山峰有他的高度h_i。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1。

    Input

    第一行三个数N,M,Q。
    第二行N个数,第i个数为h_i
    接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。
    接下来Q行,每行三个数v x k,表示一组询问。

    Output

    对于每组询问,输出一个整数表示答案。

    HINT

    【数据范围】

    N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。


    题目分析

    题目所求的是“小于等于x的边”所成连通块中的第k大,这里就会自然想到处理这一类连通块问题的策略:从小到大加边维护连通块,并在这个过程中离线处理查询。

    现在要维护的连通块信息是无序的集合,于是第一反应就是用set合并。但是显而易见的是,set不能处理第k大问题(话说暑假做“不等式组”那题时候第一反应就是用multiset处理,但是当时被查询key和第k大困扰了很久)。有一种常见的方法是采用权值线段树实现set的功能,这样一来就可以处理一些基础的查询问题。

    处理完了连通块和维护的操作,接下去的问题就是合并。权值线段树本质上还是线段树,所以使用线段树合并的套路就可以保证这一部分的复杂度。

    感觉是比较套路和数据结构的题,好像没什么营养……

      1 #include<bits/stdc++.h>
      2 const int maxn = 100035;
      3 const int maxq = 500035;
      4 const int maxm = 1000035;
      5 const int maxNode = 4000035;
      6 
      7 struct node
      8 {
      9     int l,r,val;
     10 }a[maxNode];
     11 struct QRs
     12 {
     13     int v,x,k,id;
     14     bool operator < (QRs a) const
     15     {
     16         return x < a.x;
     17     }
     18 }qr[maxq];
     19 struct Edge
     20 {
     21     int u,v,val;
     22     Edge(int a=0, int b=0, int c=0):u(a),v(b),val(c) {}
     23     bool operator < (Edge a) const
     24     {
     25         return val < a.val;
     26     }
     27 }edges[maxm];
     28 int n,m,q,dal,tot,ans[maxq];
     29 int fat[maxn],h[maxn],cnt[maxn],rt[maxn];
     30 
     31 int read()
     32 {
     33     char ch = getchar();
     34     int num = 0, fl = 1;
     35     for (; !isdigit(ch); ch=getchar())
     36         if (ch=='-') fl = -1;
     37     for (; isdigit(ch); ch=getchar())
     38         num = (num<<1)+(num<<3)+ch-48;
     39     return num*fl;
     40 }
     41 int find(int x){return x==fat[x]?x:fat[x]=find(fat[x]);}
     42 int query(int rt, int l, int r, int c)
     43 {
     44     if (l==r) return l;
     45     int mid = (l+r)>>1;
     46     if (c <= a[a[rt].l].val)
     47         return query(a[rt].l, l, mid, c);
     48     return query(a[rt].r, mid+1, r, c-a[a[rt].l].val);
     49 }
     50 int queryPos(int v, int k)
     51 {
     52     int anc = find(v);
     53     if (a[rt[anc]].val < k) return -1;
     54     return cnt[query(rt[anc], 1, cnt[0], a[rt[anc]].val-k+1)];
     55 }
     56 void update(int &rt, int l, int r, int c)
     57 {
     58     if (!rt) rt = ++tot;
     59     ++a[rt].val;
     60     if (l==r) return;
     61     int mid = (l+r)>>1;
     62     if (c <= mid) update(a[rt].l, l, mid, c);
     63     else update(a[rt].r, mid+1, r, c);
     64 }
     65 void merge(int &u, int v)
     66 {
     67     if (u*v==0){
     68         u = u?u:v;
     69         return;
     70     }
     71     a[u].val += a[v].val;
     72     merge(a[u].l, a[v].l);
     73     merge(a[u].r, a[v].r);
     74 }
     75 int main()
     76 {
     77     n = read(), m = read(), q = read();
     78     for (int i=1; i<=n; i++) h[i] = cnt[i] = read(), fat[i] = i;
     79     for (int i=1; i<=m; i++)
     80         edges[i].u = read(), edges[i].v = read(), edges[i].val = read();
     81     for (int i=1; i<=q; i++)
     82         qr[i].v = read(), qr[i].x = read(), qr[i].k = read(), qr[i].id = i;
     83     std::sort(edges+1, edges+m+1);
     84     std::sort(cnt+1, cnt+n+1);
     85     std::sort(qr+1, qr+q+1);
     86     cnt[0] = std::unique(cnt+1, cnt+n+1)-cnt-1;
     87     for (int i=1; i<=n; i++)
     88     {
     89         h[i] = std::lower_bound(cnt+1, cnt+cnt[0]+1, h[i])-cnt;
     90         update(rt[i], 1, cnt[0], h[i]);
     91     }
     92     dal = 1;
     93     for (int i=1; i<=m; i++)
     94     {
     95         int fu = find(edges[i].u), fv = find(edges[i].v);
     96         if (fu!=fv){
     97             for (; dal<=q&&qr[dal].x < edges[i].val; ++dal)
     98                 ans[qr[dal].id] = queryPos(qr[dal].v, qr[dal].k);
     99             fat[fu] = fv, merge(rt[fv], rt[fu]);
    100         }
    101     }
    102     for (int i=dal; i<=q; i++)
    103         ans[qr[i].id] = queryPos(qr[i].v, qr[i].k);
    104     for (int i=1; i<=q; i++) printf("%d
    ",ans[i]);
    105     return 0;
    106 }

    END

  • 相关阅读:
    6.11 修饰符的适用范围
    5.10 对象与垃圾回收
    5.9 枚举类
    5.8 java 11增强的Lambda表达式
    5.7 内部类
    5.6 接口
    5.5 抽象类
    5.4 final修饰符
    5.3 类成员
    5.2 Object类中两个需要被重写的方法
  • 原文地址:https://www.cnblogs.com/antiquality/p/10290425.html
Copyright © 2020-2023  润新知