[BZOj4336][BJOI2015]骑士的旅行(树链剖分+线段树)

树链剖分,对每个叶子用multiset记录前K大士兵,其余节点通过从儿子归并维护前K大士兵。过于模板。

  1 #include<set>
  2 #include<cstdio>
  3 #include<algorithm>
  4 #include<cstring>
  5 #define ls (x<<1)
  6 #define rs (ls|1)
  7 #define lson ls,L,mid
  8 #define rson rs,mid+1,R
  9 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 10 #define For(i,x) for (int i=h[x],k; i; i=nxt[i])
 11 using namespace std;
 12 
 13 const int N=40010;
 14 int n,m,u,v,op,x,y,Q,K,cnt,tim,dfn[N],son[N],sz[N],dep[N],fa[N],top[N],h[N],to[N<<1],nxt[N<<1];
 15 struct P{ int x,k; }p[N];
 16 struct Se{
 17     int tot,a[30];
 18     Se(){ tot=0; memset(a,0,sizeof(a)); }
 19     Se(const Se &b){ tot=b.tot; memcpy(a,b.a,sizeof(a)); }
 20 }T[N<<2];
 21 multiset<int>S[N<<2];
 22 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
 23 
 24 void dfs(int x){
 25     sz[x]=1; dep[x]=dep[fa[x]]+1;
 26     For(i,x) if ((k=to[i])!=fa[x]){
 27         fa[k]=x; dfs(k); sz[x]+=sz[k];
 28         if (sz[k]>sz[son[x]]) son[x]=k;
 29     }
 30 }
 31 
 32 void dfs2(int x,int tp){
 33     dfn[x]=++tim; top[x]=tp;
 34     if (son[x]) dfs2(son[x],tp);
 35     For(i,x) if ((k=to[i])!=fa[x] && k!=son[x]) dfs2(k,k);
 36 }
 37 
 38 Se merge(Se a,Se b){
 39     Se res;
 40     for (int i=1,j=1; i<=a.tot || j<=b.tot; ){
 41         if ((i<=a.tot) && (j>b.tot || b.a[j]<a.a[i])) res.a[++res.tot]=a.a[i++]; else res.a[++res.tot]=b.a[j++];
 42         if (res.tot==K) break;
 43     }
 44     return res;
 45 }
 46 
 47 void mdf(int x,int L,int R,int pos,int k,int op){
 48     if (L==R){
 49         if (!op) S[x].erase(S[x].find(k)); else S[x].insert(k);
 50         T[x].tot=0; multiset<int>::iterator it=S[x].end();
 51         while (1){
 52             if (it==S[x].begin()) break; it--;
 53             T[x].a[++T[x].tot]=*it;
 54             if (T[x].tot==K) break;
 55         }
 56         return;
 57     }
 58     int mid=(L+R)>>1;
 59     if (pos<=mid) mdf(lson,pos,k,op); else mdf(rson,pos,k,op);
 60     T[x]=merge(T[ls],T[rs]);
 61 }
 62 
 63 Se que(int x,int L,int R,int l,int r){
 64     if (L==l && r==R) return T[x];
 65     int mid=(L+R)>>1;
 66     if (r<=mid) return que(lson,l,r);
 67     else if (l>mid) return que(rson,l,r);
 68         else return merge(que(lson,l,mid),que(rson,mid+1,r));
 69 }
 70 
 71 void solve(int x,int y){
 72     Se res;
 73     for (; top[x]!=top[y]; x=fa[top[x]]){
 74         if (dep[top[x]]<dep[top[y]]) swap(x,y);
 75         res=merge(res,que(1,1,n,dfn[top[x]],dfn[x]));
 76     }
 77     if (dep[x]<dep[y]) swap(x,y);
 78     res=merge(res,que(1,1,n,dfn[y],dfn[x]));
 79     if (!res.tot) puts("-1");
 80         else{ rep(i,1,res.tot) printf("%d ",res.a[i]); puts(""); }
 81 }
 82 
 83 int main(){
 84     freopen("bzoj4336.in","r",stdin);
 85     freopen("bzoj4336.out","w",stdout);
 86     scanf("%d",&n);
 87     rep(i,2,n) scanf("%d%d",&u,&v),add(u,v),add(v,u);
 88     dfs(1); dfs2(1,1);
 89     scanf("%d",&m);
 90     rep(i,1,m) scanf("%d%d",&p[i].k,&p[i].x);
 91     scanf("%d%d",&Q,&K);
 92     rep(i,1,m) mdf(1,1,n,dfn[p[i].x],p[i].k,1);
 93     while (Q--){
 94         scanf("%d%d%d",&op,&x,&y);
 95         if (op==1) solve(x,y);
 96         if (op==2) mdf(1,1,n,dfn[p[x].x],p[x].k,0),p[x].x=y,mdf(1,1,n,dfn[p[x].x],p[x].k,1);
 97         if (op==3) mdf(1,1,n,dfn[p[x].x],p[x].k,0),p[x].k=y,mdf(1,1,n,dfn[p[x].x],p[x].k,1);
 98     }
 99     return 0;
100 }

 

转载于:https://www.cnblogs.com/HocRiser/p/9954344.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值