zoukankan      html  css  js  c++  java
  • 【bzoj3083】遥远的国度(树链剖分+线段树)

    题目描述

    zcwwzdjn在追杀十分sb的zhx,而zhx逃入了一个遥远的国度。当zcwwzdjn准备进入遥远的国度继续追杀时,守护神RapiD阻拦了zcwwzdjn的去路,他需要zcwwzdjn完成任务后才能进入遥远的国度继续追杀。

    问题是这样的:遥远的国度有n个城市,这些城市之间由一些路连接且这些城市构成了一颗树。这个国度有一个首都,我们可以把这个首都看做整棵树的根,但遥远的国度比较奇怪,首都是随时有可能变为另外一个城市的。遥远的国度的每个城市有一个防御值,有些时候RapiD会使得某两个城市之间的路径上的所有城市的防御值都变为某个值。

    RapiD想知道在某个时候,如果把首都看做整棵树的根的话,那么以某个城市为根的子树的所有城市的防御值最小是多少。

    由于RapiD无法解决这个问题,所以他拦住了zcwwzdjn希望他能帮忙。但zcwwzdjn还要追杀sb的zhx,所以这个重大的问题就被转交到了你的手上。

    输入输出格式

    输入格式:

    第1行两个整数n m,代表城市个数和操作数。

    第2行至第n行,每行两个整数 u v,代表城市u和城市v之间有一条路。

    第n+1行,有n个整数,代表所有点的初始防御值。

    第n+2行一个整数 id,代表初始的首都为id。

    第n+3行至第n+m+2行,首先有一个整数opt,如果opt=1,接下来有一个整数id,代表把首都修改为id;如果opt=2,接下来有三个整数p1 p2 v,代表将p1 p2路径上的所有城市的防御值修改为v;如果opt=3,接下来有一个整数 id,代表询问以城市id为根的子树中的最小防御值。

    输出格式:

    对于每个opt=3的操作,输出一行代表对应子树的最小点权值。

    输入输出样例

    输入样例#1: 复制
    3 7
    1 2
    1 3
    1 2 3
    1
    3 1
    2 1 1 6
    3 1
    2 2 2 5
    3 1
    2 3 3 4
    3 1
    输出样例#1: 复制
    1
    2
    3
    4

    说明

    对于20%的数据,n<=1000 m<=1000。

    对于另外10%的数据,n<=100000,m<=100000,保证修改为单点修改。

    对于另外10%的数据,n<=100000,m<=100000,保证树为一条链。

    对于另外10%的数据,n<=100000,m<=100000,没有修改首都的操作。

    对于100%的数据,n<=100000,m<=100000,0<所有权值<=2^31。

    题解

      第一眼看过去觉得是LCT

      然后发现没法维护子树信息,决定每一个点开一棵平衡树,后来发现空间要爆……

      于是好好学了一下正解

      首先查询和修改路径都是树剖的基本操作这里不提

      然后现在最重要的是换根操作咋整

      我们考虑一下,当前根与点$x$在原树中的关系无非以下几种:

      1.当前根就是点$x$——那么直接输出整棵树答案就行了

      2.当前根在原树中不在$x$的子树内——那么哪怕根换成了现在的根,$x$的子树还是没有变化,那么我们可以直接去原来的子树里查询

      3.当前根在原树中在$x$的子树内——那么我们设当前根在$u$点的子树$v$内,那么所要求的答案就是整棵树除去$v$这一棵子树的答案。至于怎么求$v$,可以从$root$往上跳重链,直到跳到$u$为止,那么就是看它从哪一个$u$点的子节点跳过来的就好了

      因为读入进来的时候路径端点和更改的值弄错了……而且忘记找$v$了……调了半天

      1 //minamoto
      2 #include<iostream>
      3 #include<cstdio>
      4 #define int unsigned int
      5 using namespace std;
      6 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
      7 char buf[1<<21],*p1=buf,*p2=buf;
      8 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
      9 inline int read(){
     10     #define num ch-'0'
     11     char ch;bool flag=0;int res;
     12     while(!isdigit(ch=getc()))
     13     (ch=='-')&&(flag=true);
     14     for(res=num;isdigit(ch=getc());res=res*10+num);
     15     (flag)&&(res=-res);
     16     #undef num
     17     return res;
     18 }
     19 char sr[1<<21],z[30];int C=-1,Z;
     20 inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
     21 inline void print(int x){
     22     if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
     23     while(z[++Z]=x%10+48,x/=10);
     24     while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
     25 }
     26 const int N=100005,inf=0xffffffff;
     27 int head[N],Next[N<<1],ver[N<<1],tot;
     28 int fa[N],dep[N],son[N],sz[N],top[N],ls[N],rs[N],cnt;
     29 int v[N],mn[N<<2],tag[N<<2];
     30 int n,m,rt;
     31 inline void add(int u,int v){
     32     ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
     33     ver[++tot]=u,Next[tot]=head[v],head[v]=tot;
     34 }
     35 void dfs1(int u){
     36     sz[u]=1,dep[u]=dep[fa[u]]+1;
     37     for(int i=head[u];i;i=Next[i]){
     38         int v=ver[i];
     39         if(v!=fa[u]){
     40             fa[v]=u,dfs1(v),sz[u]+=sz[v];
     41             if(sz[v]>sz[son[u]]) son[u]=v;
     42         }
     43     }
     44 }
     45 void dfs2(int u,int t){
     46     top[u]=t,ls[u]=++cnt;
     47     if(son[u]){
     48         dfs2(son[u],t);
     49         for(int i=head[u];i;i=Next[i]){
     50             int v=ver[i];
     51             if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
     52         }
     53     }
     54     rs[u]=cnt;
     55 }
     56 inline void pushup(int p){mn[p]=min(mn[p<<1],mn[p<<1|1]);}
     57 inline void pushdown(int p){
     58     if(tag[p])
     59     mn[p<<1]=mn[p<<1|1]=tag[p<<1]=tag[p<<1|1]=tag[p],tag[p]=0;
     60 }
     61 void build(int p,int l,int r){
     62     if(l==r) return (void)(mn[p]=v[l]);
     63     int mid=l+r>>1;
     64     build(p<<1,l,mid),build(p<<1|1,mid+1,r);
     65     pushup(p);
     66 }
     67 void update(int p,int l,int r,int ql,int qr,int x){
     68     if(ql<=l&&qr>=r) return (void)(mn[p]=tag[p]=x);
     69     pushdown(p);
     70     int mid=l+r>>1;
     71     if(ql<=mid) update(p<<1,l,mid,ql,qr,x);
     72     if(qr>mid) update(p<<1|1,mid+1,r,ql,qr,x);
     73     pushup(p);
     74 }
     75 int query(int p,int l,int r,int ql,int qr){
     76     if(ql<=l&&qr>=r) return mn[p];
     77     pushdown(p);
     78     int mid=l+r>>1,ans=inf;
     79     if(ql<=mid) cmin(ans,query(p<<1,l,mid,ql,qr));
     80     if(qr>mid) cmin(ans,query(p<<1|1,mid+1,r,ql,qr));
     81     return ans;
     82 }
     83 int find(int t,int u){
     84     while(top[u]!=top[t]){
     85         if(fa[top[u]]==t) return top[u];
     86         u=fa[top[u]];
     87     }
     88     return son[t];
     89 }
     90 void modify(int u,int v,int x){
     91     while(top[u]!=top[v]){
     92         if(dep[top[u]]<dep[top[v]]) swap(u,v);
     93         update(1,1,n,ls[top[u]],ls[u],x),u=fa[top[u]];
     94     }
     95     if(dep[u]>dep[v]) swap(u,v);
     96     update(1,1,n,ls[u],ls[v],x);
     97 }
     98 signed main(){
     99     //freopen("testdata.in","r",stdin);
    100     n=read(),m=read();
    101     for(int i=1;i<n;++i){
    102         int u=read(),v=read();add(u,v);
    103     }
    104     dfs1(1),dfs2(1,1);
    105     for(int i=1;i<=n;++i) v[ls[i]]=read();
    106     build(1,1,n);
    107     rt=read();
    108     while(m--){
    109         int opt=read(),x=read(),y,z;
    110         switch(opt){
    111             case 1:rt=x;break;
    112             case 2:y=read(),z=read(),modify(x,y,z);break;
    113             case 3:{
    114                 if(ls[rt]==ls[x]) print(mn[1]);
    115                 else if(ls[rt]<ls[x]||ls[rt]>rs[x]) print(query(1,1,n,ls[x],rs[x]));
    116                 else{
    117                     int res=inf,t=find(x,rt);
    118                     if(ls[t]>1) cmin(res,query(1,1,n,1,ls[t]-1));
    119                     if(rs[t]<n) cmin(res,query(1,1,n,rs[t]+1,n));
    120                     print(res);
    121                 }
    122                 break;
    123             }
    124         }
    125     }
    126     Ot();
    127     return 0;
    128 }
  • 相关阅读:
    windows下jmeter安装配置
    golang读取json配置文件
    磁盘分区、扇区等概念理解
    linux 命令笔记
    jvm静态分派和动态分派
    java实例初始化顺序
    计算机网络
    文件对比工具Meld
    IaaS、PaaS、SaaS
    USB 驱动常见名词解释
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/9557244.html
Copyright © 2011-2022 走看看