• BZOJ3545: [ONTAK2010]Peaks


    n<=100000,m<=500000的图有点权边权,q<=500000个询问每次问从x出发经过不超过y的边权能到的点权第K大,加强版强制在线。

    Emmmmmm有一个漂亮的方法来转化,就是对原图做MST,做的时候要连接两个点时不要直接连,新开一个点然后让这两个点连上这个点。

    这样就把边权挂到树上了,新建的点的点权代表对应的边权,由于是从小到大加边,建成的树上下面的“新建点”的点权一定小于上面的“新建点”的点权,每次回答询问在树上倍增找到点权不超过y的祖先,然后就查询这个祖先的子树内的叶子点的第K大,dfs序+主席树即可。

    然后有个小问题,图不一定联通。

      1 #include<stdio.h>
      2 #include<string.h>
      3 #include<algorithm>
      4 #include<stdlib.h>
      5 //#include<iostream>
      6 using namespace std;
      7 
      8 int n,m,q;
      9 #define maxn 200011
     10 #define maxm 2000011
     11 struct Point
     12 {
     13     int from,to,v;
     14     bool operator < (const Point &b) const {return v<b.v;}
     15 }p[maxm];
     16 
     17 int ufs[maxn];
     18 void ufsclear(int n) {for (int i=1;i<=n;i++) ufs[i]=i;}
     19 int find(int x) {return x==ufs[x]?x:(ufs[x]=find(ufs[x]));}
     20 void Union(int x,int y) {x=find(x),y=find(y);if (x==y) return;ufs[x]=y;}
     21 struct SMT
     22 {
     23     struct Node
     24     {
     25         int son[2];
     26         int cnt;
     27     }a[maxm];
     28     int size,n;
     29     void clear(int m) {n=m;size=0;a[0].cnt=0;}
     30     void insert(int pre,int &rt,int L,int R,int num)
     31     {
     32         rt=++size;
     33         a[rt].cnt=a[pre].cnt+1;
     34         if (L==R) {a[rt].son[0]=a[rt].son[1]=0;return;}
     35         const int mid=(L+R)>>1;
     36         if (num<=mid) insert(a[pre].son[0],a[rt].son[0],L,mid,num),a[rt].son[1]=a[pre].son[1];
     37         else insert(a[pre].son[1],a[rt].son[1],mid+1,R,num),a[rt].son[0]=a[pre].son[0];
     38     }
     39     void insert(int pre,int &rt,int num) {insert(pre,rt,1,n,num);}
     40 }smt;
     41 
     42 struct Edge{int to,next;}edge[maxn<<1];int first[maxn],le=2;
     43 void in(int x,int y) {Edge &e=edge[le];e.to=y;e.next=first[x];first[x]=le++;}
     44 
     45 int val[maxn],fa[maxn][20],lisan[maxn],li=0,dep[maxn],ll[maxn],list[maxn],rr[maxn],Time=0;
     46 void dfs(int x)
     47 {
     48     ll[x]=Time+1;
     49     for (int i=first[x];i;i=edge[i].next)
     50     {
     51         const Edge &e=edge[i];
     52         dep[e.to]=dep[x]+1;
     53         dfs(e.to);
     54     }
     55     if (!first[x]) list[++Time]=x;
     56     rr[x]=Time;
     57 }
     58 
     59 int lca(int x,int y)
     60 {
     61     if (dep[x]<dep[y]) {int t=x;x=y;y=t;}
     62     for (int i=18;i>=0;i--) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i];
     63     if (x==y) return x;
     64     for (int i=18;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
     65     return fa[x][0];
     66 }
     67 
     68 int rt[maxn];
     69 int main()
     70 {
     71     scanf("%d%d%d",&n,&m,&q);
     72     for (int i=1;i<=n;i++) scanf("%d",&val[i]),lisan[++li]=val[i];
     73     sort(lisan+1,lisan+1+n);li=unique(lisan+1,lisan+1+li)-lisan-1;
     74     for (int i=1;i<=n;i++) val[i]=lower_bound(lisan+1,lisan+1+li,val[i])-lisan;
     75     
     76     for (int i=1;i<=m;i++) scanf("%d%d%d",&p[i].from,&p[i].to,&p[i].v);
     77     sort(p+1,p+1+m);
     78     ufsclear(n+n);
     79     for (int i=1,cnt=1;i<=m;i++)
     80     {
     81         int x=find(p[i].from),y=find(p[i].to);
     82         if (x==y) continue;
     83         int now=n+cnt; val[now]=p[i].v;
     84         Union(x,now); Union(y,now);
     85         in(now,x); in(now,y);
     86         fa[x][0]=now;fa[y][0]=now;
     87         cnt++; if (cnt==n) break;
     88     }
     89     int tot=n+n-1;
     90     for (int j=1;j<=18;j++)
     91         for (int i=1;i<=tot;i++)
     92             fa[i][j]=fa[fa[i][j-1]][j-1];
     93     dep[tot]=1;
     94     for (int i=1;i<=tot;i++) if (!fa[i][0]) dfs(i);
     95     
     96     smt.clear(li);
     97     for (int i=1;i<=n;i++) smt.insert(rt[list[i-1]],rt[list[i]],val[list[i]]);
     98     int last=-1;
     99     for (int i=1,x,y,K;i<=q;i++)
    100     {
    101         scanf("%d%d%d",&x,&y,&K);
    102         if (last>=0) x^=last,y^=last,K^=last;
    103         int num=val[x],t=x;
    104         for (int j=18;j>=0;j--) if (fa[t][j] && val[fa[t][j]]<=y) t=fa[t][j];
    105 //        cout<<t<<endl;
    106         int u=rt[list[ll[t]-1]],v=rt[list[rr[t]]],L=1,R=li,tmp;
    107         if (smt.a[v].cnt-smt.a[u].cnt<K) {printf("%d
    ",(last=-1));continue;}
    108         while (L<R)
    109         {
    110             const int mid=(L+R)>>1;
    111             if ((tmp=smt.a[smt.a[v].son[1]].cnt-smt.a[smt.a[u].son[1]].cnt)>=K)
    112                 v=smt.a[v].son[1],u=smt.a[u].son[1],L=mid+1;
    113             else v=smt.a[v].son[0],u=smt.a[u].son[0],K-=tmp,R=mid;
    114         }
    115         printf("%d
    ",(last=lisan[L]));
    116     }
    117     return 0;
    118 }
    View Code
  • 相关阅读:
    linux上用selenium登录新浪微博,获取用户关注的用户id
    JS、Python对字符串的编码函数
    在ubuntu系统下装hadoop
    windows下python3.x的安装与使用
    python多线程、多进程、协程的使用
    python简单操作redis
    操作系统基础知识
    排序算法汇总
    网易的突然袭击
    小红书视频面试
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7944161.html
Copyright © 2020-2023  润新知