zoukankan      html  css  js  c++  java
  • bzoj4336 骑士的旅行 (树链剖分+multiset)

    首先大概有一个树剖+树套树的做法,但我哪会写啊

    然后发现k很小,如果用线段树记每个区间前k大的的话,可以O(k)地合并

    而且一个点还有可能有好多个骑士,所以要用multiset维护一下

    然后树剖就好啦

      1 #include<bits/stdc++.h>
      2 #define pa pair<int,int>
      3 #define CLR(a,x) memset(a,x,sizeof(a))
      4 #define IT multiset<int>::iterator
      5 using namespace std;
      6 typedef long long ll;
      7 const int maxn=4e4+10,maxk=25;
      8 
      9 inline ll rd(){
     10     ll x=0;char c=getchar();int neg=1;
     11     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
     12     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
     13     return x*neg;
     14 }
     15 
     16 int eg[maxn*2][2],egh[maxn],ect,smr[maxn][2];
     17 int N,M,Q,K;
     18 int wson[maxn],dfn[maxn],dep[maxn],siz[maxn],top[maxn],fa[maxn],tot;
     19 int fr[maxn*4][maxk],id[maxn],ans[maxk],tmp[maxk];
     20 multiset<int,greater<int> > st[maxn];
     21 
     22 inline void adeg(int a,int b){
     23     eg[++ect][0]=b;eg[ect][1]=egh[a];egh[a]=ect;
     24 }
     25 
     26 void dfs1(int x){
     27     siz[x]=1;int mm=0;
     28     for(int i=egh[x];i;i=eg[i][1]){
     29         int b=eg[i][0];
     30         if(b==fa[x]) continue;
     31         fa[b]=x;dep[b]=dep[x]+1;
     32         dfs1(b);siz[x]+=siz[b];
     33         if(siz[b]>mm) mm=siz[b],wson[x]=b;
     34     }
     35 }
     36 void dfs2(int x){
     37     dfn[x]=++tot;id[tot]=x;
     38     top[x]=(x==wson[fa[x]]?top[fa[x]]:x);
     39     if(wson[x]) dfs2(wson[x]);
     40     for(int i=egh[x];i;i=eg[i][1]){
     41         int b=eg[i][0];
     42         if(b==wson[x]||b==fa[x]) continue;
     43         dfs2(b);
     44     }
     45 }
     46 
     47 inline void update(int p){
     48     int l=p<<1,r=p<<1|1;
     49     int a=1,b=1,i=0;
     50     for(;a<=fr[l][0]&&i<K;a++){
     51         for(;b<=fr[r][0]&&fr[r][b]>fr[l][a]&&i<K;b++)
     52             fr[p][++i]=fr[r][b];
     53         if(i<K) fr[p][++i]=fr[l][a];
     54     }for(;b<=fr[r][0]&&i<K;b++) fr[p][++i]=fr[r][b];
     55     fr[p][0]=i;
     56 }
     57 
     58 void build(int p,int l,int r){
     59     if(l==r){
     60         int i=0;
     61         for(IT it=st[id[l]].begin();i<K&&it!=st[id[l]].end();it++){
     62             fr[p][++i]=*it;
     63         }fr[p][0]=i;
     64     }else{
     65         int m=l+r>>1;
     66         build(p<<1,l,m);build(p<<1|1,m+1,r);
     67         update(p);
     68     }
     69 }
     70 
     71 void query(int p,int l,int r,int x,int y){
     72     if(x<=l&&r<=y){
     73         if(!ans[0]){
     74             memcpy(ans,fr[p],sizeof(ans));
     75             return;
     76         }
     77         int a=1,b=1,i=0;
     78         for(;a<=fr[p][0]&&i<K;a++){
     79             for(;b<=ans[0]&&ans[b]>fr[p][a]&&i<K;b++)
     80                 tmp[++i]=ans[b];
     81             if(i<K) tmp[++i]=fr[p][a];
     82         }for(;b<=ans[0]&&i<K;b++) tmp[++i]=ans[b];
     83         tmp[0]=i;
     84         memcpy(ans,tmp,sizeof(ans));
     85     }else{
     86         int m=l+r>>1;
     87         if(x<=m) query(p<<1,l,m,x,y);
     88         if(y>=m+1) query(p<<1|1,m+1,r,x,y);
     89     }
     90 }
     91 
     92 void change(int p,int l,int r,int x,int y,bool b){
     93     if(l==r){
     94         if(!b) st[id[l]].erase(st[id[l]].find(y));
     95         else st[id[l]].insert(y);
     96         int i=0;
     97         for(IT it=st[id[l]].begin();i<K&&it!=st[id[l]].end();it++){
     98             fr[p][++i]=*it;
     99         }fr[p][0]=i;
    100     }else{
    101         int m=l+r>>1;
    102         if(x<=m) change(p<<1,l,m,x,y,b);
    103         else change(p<<1|1,m+1,r,x,y,b);
    104         update(p);
    105     }
    106 }
    107 
    108 void solve1(int x,int y){
    109     ans[0]=0,tmp[0]=0;
    110     while(top[x]!=top[y]){
    111         if(dep[top[x]]<dep[top[y]]) swap(x,y);
    112         query(1,1,N,dfn[top[x]],dfn[x]);
    113         // printf("%d %d
    ",dfn[top[x]],x);
    114         x=fa[top[x]];
    115     }
    116     if(dep[x]<dep[y]) swap(x,y);
    117     query(1,1,N,dfn[y],dfn[x]);
    118 }
    119 
    120 void solve2(int x,int y){
    121     change(1,1,N,dfn[smr[x][1]],smr[x][0],0);
    122     change(1,1,N,dfn[y],smr[x][0],1);
    123     smr[x][1]=y;
    124 }
    125 void solve3(int x,int y){
    126     change(1,1,N,dfn[smr[x][1]],smr[x][0],0);
    127     change(1,1,N,dfn[smr[x][1]],y,1);
    128     smr[x][0]=y;
    129 }
    130 
    131 int main(){
    132     //freopen("","r",stdin);
    133     int i,j,k;
    134     N=rd();
    135     for(i=1;i<N;i++){
    136         int a=rd(),b=rd();
    137         adeg(a,b);adeg(b,a);
    138     }
    139     M=rd();
    140     for(i=1;i<=M;i++){
    141         smr[i][0]=rd(),smr[i][1]=rd();
    142         st[smr[i][1]].insert(smr[i][0]);
    143     }
    144     Q=rd(),K=rd();
    145     dep[1]=1;dfs1(1);
    146     dfs2(1);build(1,1,N);
    147     for(j=1;j<=Q;j++){
    148         int a=rd(),b=rd(),c=rd();
    149         if(a==1){
    150             solve1(b,c);
    151             if(ans[0]==0) printf("-1");
    152             for(i=1;i<=ans[0];i++)
    153                 printf("%d ",ans[i]);
    154             printf("
    ");
    155         }else if(a==2) solve2(b,c);
    156         else solve3(b,c);
    157     }
    158     return 0;
    159 }
  • 相关阅读:
    二进制、八进制、十进制、十六进制的转换
    loadrunner-检查点
    loadrunner-集合点
    loadrunner-事务
    软件测试分类总结
    《黑客与画家》读后感
    说两个我在工作中有价值的bug
    HTTP状态码
    Android开发学习——android与服务器端数据交互
    Android开发学习——Volley框架
  • 原文地址:https://www.cnblogs.com/Ressed/p/9794694.html
Copyright © 2011-2022 走看看