zoukankan      html  css  js  c++  java
  • Bzoj3545 [ONTAK2010]Peaks

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 2038  Solved: 535

    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

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

    Sample Input

    10 11 4
    1 2 3 4 5 6 7 8 9 10
    1 4 4
    2 5 3
    9 8 2
    7 8 10
    7 1 4
    6 7 1
    6 4 8
    2 1 5
    10 8 10
    3 4 7
    3 4 6
    1 5 2
    1 5 6
    1 5 8
    8 9 2

    Sample Output

    6
    1
    -1
    8


    HINT

    【数据范围】

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

    Source

    Kruskal  启发式合并 树 treap 脑洞题

    将询问离线,按询问x值从小到大排序,回答每个询问前将x值小于询问值的边加进集合,进行启发式合并。

    用treap维护集合内的结点,进行排名查询以回答询问。

    要回答的是目标山的高度,不是编号←样例真是充满了误导性

    算法比较好想,然而并不会写treap的启发式合并……

    各种开脑洞,发现要么太难实现,要么实现了不能保证二叉树性质WAWAWA

    依稀记得听说过可持久化treap的合并是以某个权值为界把treap拆分开,再合并成一整棵新树,想想就好难写。

    最后放弃了挣扎,选择了暴力把一棵treap上的点全建到另一棵treap上。

    然而一对拍又挂了,检查了好久好久,发现合并时候少传了一个地址。

    于是一下午+半个晚上就水过去了。

    随机数种子很好用,并没有特殊的意义(认真脸)

      1 /*by SilverN*/
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdio>
      6 #include<cmath>
      7 #include<vector>
      8 using namespace std;
      9 const int mxn=120010;
     10 int read(){
     11     int x=0,f=1;char ch=getchar();
     12     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     13     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
     14     return x*f;
     15 }
     16 struct edge{
     17     int x,y,w;
     18     bool operator < (edge b)const{return w<b.w;}
     19 }e[mxn*5];
     20 struct QUE{
     21     int v,x,k,id;
     22     bool operator < (QUE b)const{return x<b.x;}
     23 }q[mxn*5];
     24 //
     25 int fa[mxn],sz[mxn];
     26 int find(int x){
     27     return fa[x]==x?x:fa[x]=find(fa[x]);
     28 }
     29 //
     30 struct node{
     31     int l,r;
     32     int v,sz,cnt;
     33     int rand;
     34 }t[mxn*5];
     35 int rot[mxn],cnt;
     36 void pushup(int x){
     37     t[x].sz=t[t[x].l].sz+t[t[x].r].sz+t[x].cnt;
     38 }
     39 void Rt(int &k){
     40     int now=t[k].l;
     41     t[k].l=t[now].r;
     42     t[now].r=k;
     43     pushup(k);pushup(now);
     44     k=now;
     45     return;
     46 }
     47 void Lt(int &k){
     48     int now=t[k].r;
     49     t[k].r=t[now].l;
     50     t[now].l=k;
     51     pushup(k);pushup(now);
     52     k=now;
     53     return;
     54 }
     55 void DEBUG(){
     56     printf("Debug
    ");
     57     for(int j=0;j<=cnt;j++){
     58         printf("#%d: lc:%d rc:%d sz:%d cnt:%d
    ",j,t[j].l,t[j].r,t[j].sz,t[j].cnt);
     59     }
     60     printf("fin
    ");
     61     return;
     62 }
     63 int bin[mxn*2],top=0;
     64 void insert(int v,int c,int &rt){
     65     if(!rt){
     66         if(top)rt=bin[top--];
     67         else rt=++cnt;
     68         t[rt].cnt=t[rt].sz=c;
     69         t[rt].v=v;
     70         t[rt].rand=rand();
     71         t[rt].l=t[rt].r=0;
     72         return;
     73     }
     74     t[rt].sz+=c;
     75     if(t[rt].v==v) t[rt].cnt+=c;
     76     else if(v<t[rt].v){
     77         insert(v,c,t[rt].l);
     78         if(t[t[rt].l].rand>t[rt].rand){
     79             Rt(rt);
     80         }
     81     }
     82     else{
     83         insert(v,c,t[rt].r);
     84         if(t[t[rt].r].rand>t[rt].rand){
     85             Lt(rt);
     86         }
     87     }
     88     return;
     89 }
     90 void Merge(int &x,int &y){//y也会被改变,需要传地址 
     91     if(!x)return;
     92     Merge(t[x].l,y);
     93     Merge(t[x].r,y);
     94     int tmp=x;
     95     x=0;
     96     insert(t[tmp].v,t[tmp].cnt,y);
     97     bin[++top]=tmp;
     98     return;
     99 }
    100 int ask_rank(int rt,int k){
    101     if(!rt)return 0;
    102     if(t[t[rt].r].sz>=k)return ask_rank(t[rt].r,k);
    103     else if(t[t[rt].r].sz+t[rt].cnt>=k)return t[rt].v;
    104     else return ask_rank(t[rt].l,k-t[t[rt].r].sz-t[rt].cnt);
    105 }
    106 void link(int u,int v){
    107     u=find(u);v=find(v);
    108     if(u==v)return;
    109     if(t[u].sz<t[v].sz)swap(u,v);
    110     Merge(rot[v],rot[u]);//v向u合并 
    111     fa[v]=u;
    112     return;
    113 }
    114 int n,m,Q;
    115 int h[mxn],ans[mxn*5];
    116 
    117 void solve(){
    118     int i,j;
    119     srand(19260817);
    120     for(i=1;i<=n;i++){
    121         insert(h[i],1,rot[i]);
    122     }//treap init 
    123     int hd=1;
    124     for(i=1;i<=Q;i++){
    125         while(e[hd].w<=q[i].x && hd<=m){
    126             link(e[hd].x,e[hd].y);
    127             hd++;
    128         }
    129         int x=find(q[i].v);
    130         int res=ask_rank(rot[x],q[i].k);
    131         if(!res)ans[q[i].id]=-1;
    132         else ans[q[i].id]=res;
    133     }
    134     return;
    135 }
    136 int main(){
    137 //    freopen("Input.in","r",stdin);
    138     int i,j;
    139     n=read();m=read();Q=read();
    140     for(i=1;i<=n;i++){
    141         h[i]=read();
    142         fa[i]=i;
    143     }
    144     for(i=1;i<=m;i++){
    145         e[i].x=read();e[i].y=read();e[i].w=read();
    146     }
    147     for(i=1;i<=Q;i++){
    148         q[i].v=read();q[i].x=read();q[i].k=read();q[i].id=i;
    149     }
    150     sort(e+1,e+m+1);
    151     sort(q+1,q+Q+1);
    152     solve();
    153     for(i=1;i<=Q;i++){
    154         printf("%d
    ",ans[i]);
    155     }
    156     return 0;
    157 }
  • 相关阅读:
    作业day17
    python开发学习day17 (生成器;面向过程;三元表达式;生成式,内置函数)
    作业day16
    python开发学习day16 (三层装饰器;迭代器)
    python开发学习day15 (叠加装饰器;递归调用;匿名函数)
    作业day14
    python开发学习day14 (装饰器;语法糖;装饰器模板)
    python开发学习day13 (函数嵌套;名称空间与作用域;闭包函数)
    作业day12
    Python-简单算法程序
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6657352.html
Copyright © 2011-2022 走看看