zoukankan      html  css  js  c++  java
  • [BZOJ4811][YNOI2017]由乃的OJ(树链剖分+线段树)

    起床困难综合症那题,只要从高往低贪心,每次暴力跑一边看这一位输入0和1分别得到什么结果即可。

    放到序列上且带修改,只要对每位维护一个线段树,每个节点分别记录0和1从左往右和从右往左走完这段区间后变成的数即可。

    放到树上,只要树链剖分即可。但这里有一个很大的常数k,实际上我们只需要一个数就可以记录64个二进制位的信息,于是复杂度$O(nlog^2 n)$

    小错误毁一生。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<iostream>
      4 #include<algorithm>
      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 typedef unsigned long long ll;
     12 using namespace std;
     13 
     14 const int N=100010;
     15 ll z,I=1;
     16 int n,m,k,u,v,x,y,op,cnt,tim,pos[N],sz[N],dep[N],son[N],fa[N],dfn[N],top[N];
     17 int h[N],to[N<<1],nxt[N<<1];
     18 struct P{ int op; ll x; }p[N];
     19 struct D{ ll s0,s1; }v1[N<<2],v2[N<<2];
     20 struct S{ int l,r; }lp[N],rp[N];
     21 
     22 void add(int u,int v){ to[++cnt]=v; nxt[cnt]=h[u]; h[u]=cnt; }
     23 
     24 void work(int x,P p){
     25     if (p.op==1) v1[x]=v2[x]=(D){0,p.x};
     26     if (p.op==2) v1[x]=v2[x]=(D){p.x,-1};
     27     if (p.op==3) v1[x]=v2[x]=(D){p.x,p.x^(-1)};
     28 }
     29 
     30 D operator +(D a,D b){ return (D){((~a.s0)&b.s0)|(a.s0&b.s1),((~a.s1)&b.s0)|(a.s1&b.s1)}; }
     31 void upd(int x){ v1[x]=v1[ls]+v1[rs]; v2[x]=v2[rs]+v2[ls]; }
     32 
     33 void dfs(int x){
     34     sz[x]=1; dep[x]=dep[fa[x]]+1;
     35     For(i,x) if ((k=to[i])!=fa[x]){
     36         fa[k]=x; dfs(k); sz[x]+=sz[k];
     37         if (sz[k]>sz[son[x]]) son[x]=k;
     38     }
     39 }
     40 
     41 void dfs2(int x,int tp){
     42     top[x]=tp; dfn[x]=++tim; pos[tim]=x;
     43     if (son[x]) dfs2(son[x],tp);
     44     For(i,x) if ((k=to[i])!=fa[x] && k!=son[x]) dfs2(k,k);
     45 }
     46 
     47 void build(int x,int L,int R){
     48     if (L==R){ work(x,p[pos[L]]); return; }
     49     int mid=(L+R)>>1;
     50     build(lson); build(rson); upd(x);
     51 }
     52 
     53 void mdf(int x,int L,int R,int pos,P p){
     54     if (L==R){ work(x,p); return; }
     55     int mid=(L+R)>>1;
     56     if (pos<=mid) mdf(lson,pos,p); else mdf(rson,pos,p);
     57     upd(x);
     58 }
     59 
     60 D que(int x,int L,int R,int l,int r,int k){
     61     if (L==l && r==R) return (k==1) ? v1[x] : v2[x];
     62     int mid=(L+R)>>1;
     63     if (r<=mid) return que(lson,l,r,k);
     64     else if (l>mid) return que(rson,l,r,k);
     65         else{
     66             D a=que(lson,l,mid,k),b=que(rson,mid+1,r,k);
     67             return (k==1) ? a+b : b+a;
     68         }
     69 }
     70 
     71 void solve(int x,int y,ll z){
     72     int ld=0,rd=0,rev=0;
     73     S *L=lp,*R=rp;
     74     for (; top[x]!=top[y]; x=fa[top[x]]){
     75         if (dep[top[x]]<dep[top[y]]) rev^=1,swap(x,y),swap(ld,rd),swap(L,R);
     76         L[++ld]=(S){dfn[top[x]],dfn[x]};
     77     }
     78     if (dep[x]<dep[y]) rev^=1,swap(x,y),swap(ld,rd),swap(L,R);
     79     L[++ld]=(S){dfn[y],dfn[x]};
     80     if (rev) swap(ld,rd),swap(L,R);
     81     D res=(D){0,-1};
     82     rep(i,1,ld) res=res+que(1,1,n,L[i].l,L[i].r,2);
     83     for (int i=rd; i; i--) res=res+que(1,1,n,R[i].l,R[i].r,1);
     84     ll s=0,c=0;
     85     for (int i=k-1; ~i; i--)
     86         if (res.s0&(I<<i)) s+=I<<i;
     87             else if ((res.s1&(I<<i)) && c+(I<<i)<=z) c+=I<<i,s+=I<<i;
     88     printf("%llu
    ",s);
     89 }
     90 
     91 int main(){
     92     freopen("bzoj4811.in","r",stdin);
     93     freopen("bzoj4811.out","w",stdout);
     94     scanf("%d%d%d",&n,&m,&k);
     95     rep(i,1,n) scanf("%d%llu",&p[i].op,&p[i].x);
     96     rep(i,2,n) scanf("%d%d",&u,&v),add(u,v),add(v,u);
     97     dfs(1); dfs2(1,1); build(1,1,n);
     98     rep(i,1,m){
     99         scanf("%d%d%d%llu",&op,&x,&y,&z);
    100         if (op==1) solve(x,y,z); else mdf(1,1,n,dfn[x],(P){y,z});
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    lintcode:previous permutation上一个排列
    lintcode : 二叉树的序列化和反序列化
    lintcode : find peak element 寻找峰值
    lintcode 中等题:搜索旋转排序数组II
    lintcode :搜索旋转排序数组
    lintcode: search for a range 搜索区间
    lintcode:最大子数组差
    lintcode:最大子数组II
    lintcode :最大子数组
    lintcode : 平衡二叉树
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10129342.html
Copyright © 2011-2022 走看看