• bzoj3551 Peaks加强版


    这个题……感觉离线和在线的代码难度差不多(pb_ds不要说话)。

    离线的话,就是把所有询问按照w排个序,然后一边Kruskal+平衡树启发式合并一边回答询问就好了。

    在线也不难写。首先Kruskal重构树(这个Kruskal重构树是不按秩合并还要添虚点的那种……),那么每个点可以到达的点一定在某个子树里。子树的dfs序是连续的,所以可以对dfs序建主席树来求区间k大。又因为只有叶子节点的点权是有意义的,所以可以只对叶子的dfs序建主席树。查询的时候倍增跳到最高的w<=询问的w的点然后主席树就好了。

    其实树剖跳父亲也可以,先跳整条链,整条链跳不动的时候就在最后一条链上二分,也是O(logn)的。不过可能是太弱,二分写挂了,结果WA到死……无奈用倍增重写了一遍。

    限时20s,结果我跑了19.8s,这速度真是感人肺腑……

    还有,copy的那个a一开始忘了+1了,调了一节课,虚死……

      1 /**************************************************************
      2     Problem: 3551
      3     User: hzoier
      4     Language: C++
      5     Result: Accepted
      6     Time:19800 ms
      7     Memory:114432 kb
      8 ****************************************************************/
      9 #include<cstdio>
     10 #include<cstring>
     11 #include<algorithm>
     12 using namespace std;
     13 const int maxn=200010,maxe=500010;
     14 struct edge{
     15     int from,to,w;
     16     bool operator<(const edge &e)const{return w<e.w;}
     17 }e[maxe+maxn];
     18 void Kruskal();
     19 int findroot(int);
     20 void mergeset(int,int);
     21 void dfs(int);
     22 void build(int,int,int&,int);
     23 void query(int,int,int,int);
     24 int sm[maxn<<5],lc[maxn<<5],rc[maxn<<5],root[maxn],tree_cnt=0;
     25 int n,M=0,m,q,h[maxn],a[maxn],cnt,prt[maxn],w[maxn],f[maxn][20],ch[maxn][2],L[maxn],R[maxn],pr=0,x,d,k,ans;
     26 int main(){
     27     scanf("%d%d%d",&n,&m,&q);
     28     while((1<<M)<(n<<1))M++;
     29     for(int i=1;i<=n;i++)scanf("%d",&h[i]);
     30     copy(h+1,h+n+1,a+1);
     31     sort(a+1,a+n+1);
     32     for(int i=1;i<=n;i++)h[i]=lower_bound(a+1,a+n+1,h[i])-a;
     33     for(int i=1;i<=m;i++)scanf("%d%d%d",&e[i].from,&e[i].to,&e[i].w);
     34     for(int i=2;i<=n;i++){
     35         e[++m].from=1;
     36         e[m].to=i;
     37         e[m].w=~(1<<31);
     38     }
     39     cnt=n;
     40     Kruskal();
     41     dfs(cnt);
     42     for(int j=1;j<=M;j++)for(int i=1;i<=cnt;i++)f[i][j]=f[f[i][j-1]][j-1];
     43     while(q--){
     44         scanf("%d%d%d",&x,&d,&k);
     45         if(ans!=-1){x^=ans;d^=ans;k^=ans;}
     46         for(int j=M;j!=-1;j--)if(f[x][j]&&w[f[x][j]]<=d)x=f[x][j];
     47         query(1,n,root[R[x]],root[L[x]-1]);
     48         printf("%d
    ",ans);
     49     }
     50     return 0;
     51 }
     52 void Kruskal(){
     53     for(int i=1;i<=n;i++)prt[i]=i;
     54     stable_sort(e+1,e+m+1);
     55     for(int i=1;i<=m;i++)if(findroot(e[i].from)!=findroot(e[i].to)){
     56         cnt++;
     57         prt[cnt]=cnt;
     58         w[cnt]=e[i].w;
     59         ch[cnt][0]=findroot(e[i].from);
     60         ch[cnt][1]=findroot(e[i].to);
     61         mergeset(e[i].from,cnt);
     62         mergeset(e[i].to,cnt);
     63     }
     64 }
     65 int findroot(int x){return prt[x]==x?x:(prt[x]=findroot(prt[x]));}
     66 void mergeset(int x,int y){prt[findroot(x)]=findroot(y);}
     67 void dfs(int x){
     68     if(ch[x][0]){
     69         f[ch[x][0]][0]=f[ch[x][1]][0]=x;
     70         dfs(ch[x][0]);
     71         dfs(ch[x][1]);
     72         L[x]=L[ch[x][0]];
     73         R[x]=R[ch[x][1]];
     74     }
     75     else{
     76         k=h[x];
     77         build(1,n,root[pr+1],root[pr]);
     78         L[x]=R[x]=++pr;
     79     }
     80 }
     81 void build(int l,int r,int &rt,int pr){
     82     sm[rt=++tree_cnt]=sm[pr]+1;
     83     if(l==r)return;
     84     lc[rt]=lc[pr];rc[rt]=rc[pr];
     85     int mid=(l+r)>>1;
     86     if(k<=mid)build(l,mid,lc[rt],lc[pr]);
     87     else build(mid+1,r,rc[rt],rc[pr]);
     88 }
     89 void query(int l,int r,int rt,int pr){
     90     if(sm[rt]-sm[pr]<k){
     91         ans=-1;
     92         return;
     93     }
     94     if(l==r){
     95         ans=a[l];
     96         return;
     97     }
     98     int mid=(l+r)>>1;
     99     if(k<=sm[rc[rt]]-sm[rc[pr]])query(mid+1,r,rc[rt],rc[pr]);
    100     else{
    101         k-=sm[rc[rt]]-sm[rc[pr]];
    102         query(l,mid,lc[rt],lc[pr]);
    103     }
    104 }
    View Code

    尽头和开端,总有一个在等你。

  • 相关阅读:
    python-flask-SQLAlchemy
    python-flask-script定制manage命令
    python-flask框架
    python-flask-wtforms
    python-思路整理-虚拟环境
    python--django-admin定制页面流程:
    友盟iOS微信登陆没有回调的原因
    用同一个工程创建两个不同版本的应用
    简单方法实现手势解锁
    iOS开发中地图开发的简单应用
  • 原文地址:https://www.cnblogs.com/hzoier/p/6056980.html
Copyright © 2020-2023  润新知