zoukankan      html  css  js  c++  java
  • BZOJ 2286: [Sdoi2011]消耗战 虚树 树形dp 动态规划 dfs序

    https://www.lydsy.com/JudgeOnline/problem.php?id=2286

    wa了两次因为lca犯了zz错误

    这道题如果不多次询问的话就是裸dp。

    一棵树上多次询问,且总共询问的点数较小(能够承受得住加个logn的复杂度(常数就不管了,按理说还要*2吧))可以用虚树来处理。

    虚树就是对每次询问将有用的点建一棵树,每次询问查询m个点,则这棵树最多m*2个点(太优秀了)。

    这个虚树的建立过程是用栈维护一条链,每加入一个点就把她和前一条链的叶子节点的lca和这个点本身加入虚树中,然后将当前链的叶子节点改为当前加入的点。

    dfs序是个好东西,它帮助维护了这条链和后面点的关系(的逻辑性?(看到代码就懂了吧,反正就很有逻辑就对了))。

    所以我之前为什么要学树链剖分,树链剖分什么用都没有嘤嘤嘤,最喜欢倍增了。(日常抛弃旧爱)

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 #include<cmath>
      6 #include<map>
      7 using namespace std;
      8 #define LL long long
      9 const int maxn=250010;
     10 const LL minf=(LL)5e17;
     11 int n,m;
     12 struct nod{
     13     int nex,y,v;
     14 };nod e[maxn*2];nod e1[maxn*4];
     15 int head[maxn]={},tot=0;
     16 int head1[maxn]={},tot1=0;
     17 int id[maxn]={},cnt=0;
     18 int fa[maxn][22]={},dep[maxn]={};
     19 LL dis[maxn]={},f[maxn]={};
     20 int a[maxn]={},tly=0;
     21 int sta[maxn]={},tai=0;
     22 inline int mread(){
     23     int x=0,f=1;char ch=getchar();
     24     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     25     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     26     return x*f;
     27 }
     28 inline void init(int x,int y,int v){
     29     e[++tot].y=y;e[tot].v=v;e[tot].nex=head[x];head[x]=tot;
     30 }
     31 inline void init1(int x,int y){
     32     if(x==y)return;
     33     e1[++tot1].y=y;e1[tot1].nex=head1[x];head1[x]=tot1;
     34 }
     35 void dfs(int x,int pa){
     36     fa[x][0]=pa;id[x]=++cnt;
     37     for(int i=1;fa[fa[x][i-1]][i-1]!=0;++i)fa[x][i]=fa[fa[x][i-1]][i-1];
     38     for(int i=head[x];i;i=e[i].nex){
     39         int y=e[i].y;
     40         if(y==pa)continue;
     41         dis[y]=dis[x]<e[i].v?dis[x]:e[i].v;
     42         dep[y]=dep[x]+1;
     43         dfs(y,x);
     44     }
     45 }
     46 bool mcmp(int x,int y){return id[x]<id[y];}
     47 int getlca(int x,int y){
     48     if(dep[x]<dep[y])swap(x,y);
     49     for(int i=19;i>=0;--i){
     50         if(!fa[x][i])continue;
     51         if(dep[fa[x][i]]>=dep[y])x=fa[x][i];
     52         if(dep[x]==dep[y])break;
     53     }
     54     if(x==y)return x;
     55     for(int i=19;i>=0;--i){
     56         if(!fa[x][i])continue;
     57         if(fa[x][i]!=fa[y][i]){x=fa[x][i];y=fa[y][i];}
     58     }
     59     return fa[x][0];
     60 }
     61 void dfs1(int x){
     62     f[x]=dis[x];LL v=0;
     63     for(int i=head1[x];i;i=e1[i].nex){
     64         dfs1(e1[i].y);
     65         v+=f[e1[i].y];
     66     }
     67     if(v)f[x]=min(f[x],v);
     68     head1[x]=0;
     69 }
     70 void cutit(){
     71     int q=mread(); for(int i=1;i<=q;++i)a[i]=mread();
     72     sort(a+1,a+1+q,mcmp); tly=1;
     73     for(int i=2;i<=q;++i){if(getlca(a[i],a[tly])!=a[tly])a[++tly]=a[i];}
     74     //由根节点到叶子节点的每条链上至多只有一个点
     75     tai=1;sta[1]=1;tot1=0;int lc;
     76     for(int i=1;i<=tly;i++){//sta按照dfs序维护了一条链
     77         lc=getlca(sta[tai],a[i]);
     78         for(;tai>1;){//更改链向下延伸的方向,把之前方向的点连上
     79             if(dep[sta[tai-1]]<=dep[lc]){
     80                 init1(lc,sta[tai]);tai--;
     81                 if(sta[tai]!=lc)sta[++tai]=lc;
     82                 break;
     83             }init1(sta[tai-1],sta[tai]);tai--;
     84         }
     85         if(sta[tai]!=a[i])sta[++tai]=a[i];
     86     }
     87     while(--tai)init1(sta[tai],sta[tai+1]);
     88     dfs1(1);
     89     printf("%lld
    ",f[1]);
     90 }
     91 int main(){
     92     int x,y,v;
     93     n=mread();
     94     for(int i=1;i<n;++i){
     95         x=mread();y=mread();v=mread();
     96         init(x,y,v);init(y,x,v);
     97     }
     98     dis[1]=minf; dep[1]=0; dfs(1,0);
     99     m=mread(); for(int i=1;i<=m;++i) cutit();
    100     return 0;
    101 }
    View Code

  • 相关阅读:
    2017-2018-1 20155330 《信息安全系统设计基础》第11周学习总结
    2017-2018-1 20155321 20155330 《信息安全技术》 实验四 木马及远程控制技术
    2017-2018-1 20155330 《信息安全系统设计基础》第10周课堂测试&课下作业
    2017-2018-1 20155330 《信息安全系统设计基础》第9周学习总结
    2017-2018-1 20155321 20155330 《信息安全系统设计基础》实验三——实时系统
    2017-2018-1 20155330 《信息安全系统设计基础》加分项目--实现mypwd
    Web基础
    附录2
    C++中cout.setf()函数
    C++ 输入输出运算符重载
  • 原文地址:https://www.cnblogs.com/137shoebills/p/9056617.html
Copyright © 2011-2022 走看看