zoukankan      html  css  js  c++  java
  • bzoj 4448: [Scoi2015]情报传递

    Description
    奈特公司是一个巨大的情报公司,它有着庞大的情报网络。情报网络中共有n名情报员。每名情报员口J-能有
    若T名(可能没有)下线,除1名大头日外其余n-1名情报员有且仅有1名上线。奈特公司纪律森严,每
    名情报员只能与自己的上、下线联系,同时,情报网络中仟意两名情报员一定能够通过情报网络传递情报。
    奈特公司每天会派发以下两种任务中的一个任务:
    1.搜集情报:指派T号情报员搜集情报
    2.传递情报:将一条情报从X号情报员传递给Y号情报员
    情报员最初处于潜伏阶段,他们是相对安全的,我们认为此时所有情报员的危险值为0;-旦某个情报员开
    始搜集情报,他的危险值就会持续增加,每天增加1点危险值(开始搜集情报的当天危险值仍为0,第2天
    危险值为1,第3天危险值为2,以此类推)。传递情报并不会使情报员的危险值增加。
    为了保证传递情报的过程相对安全,每条情报都有一个风险控制值C。余特公司认为,参与传递这条情
    报的所有情报员中,危险值大于C的情报员将对该条情报构成威胁。现在,奈特公司希望知道,对于每
    个传递情报任务,参与传递的情报员有多少个,其中对该条情报构成威胁的情报员有多少个。

    解题报告:
    用时:1h,2WA
    和上题类似,这里的风险控制值实质上是询问开始收集情报时刻小于 (i-c) 的节点,所以我们就以天数为下标建立主席树,然后查询路径直接用树链剖分查找即可

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define RG register
    #define il inline
    #define iter iterator
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    const int N=200005;
    int head[N],num=0,nxt[N<<1],to[N<<1],n,m,fa[N];
    void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
    struct question{int x,y,c;}q[N];int mt=0,tx[N],root[N];
    int dep[N],top[N],DFN=0,id[N],sz[N],son[N];
    void dfs1(int x){
       int u;sz[x]=1;
       for(int i=head[x];i;i=nxt[i]){
          u=to[i];if(dep[u])continue;
          dep[u]=dep[x]+1;fa[u]=x;
          dfs1(u);
          sz[x]+=sz[u];
          if(sz[u]>sz[son[x]])son[x]=u;
       }
    }
    void dfs2(int x,int tp){
       top[x]=tp;id[x]=++DFN;
       if(son[x])dfs2(son[x],tp);
       for(int i=head[x];i;i=nxt[i])
          if(to[i]!=son[x] && to[i]!=fa[x])dfs2(to[i],to[i]);
    }
    int totnode=0;
    struct node{int l,r,s;}t[N*80];
    void updata(int &rt,int last,int l,int r,int sa){
       rt=++totnode;t[rt]=t[last];
       if(l==r){t[rt].s++;return ;}
       int mid=(l+r)>>1;
       if(sa>mid)updata(t[rt].r,t[last].r,mid+1,r,sa);
       else updata(t[rt].l,t[last].l,l,mid,sa);
       t[rt].s=t[t[rt].l].s+t[t[rt].r].s;
    }
    int query(int rt,int l,int r,int sa,int se){
       if(l>se || r<sa)return 0;
       if(sa<=l && r<=se)return t[rt].s;
       int mid=(l+r)>>1;
       return query(t[rt].l,l,mid,sa,se)+query(t[rt].r,mid+1,r,sa,se);
    }
    void solve(int x,int y,int co){
       int ret=0,dist=dep[x]+dep[y];
       while(top[x]!=top[y]){
          if(dep[top[x]]<dep[top[y]])swap(x,y);
          if(co>0)ret+=query(root[co],1,n,id[top[x]],id[x]);
          x=fa[top[x]];
       }
       if(id[x]>id[y])swap(x,y);
       if(co>0)ret+=query(root[co],1,n,id[x],id[y]);
       dist-=dep[x]<<1;
       printf("%d %d
    ",dist+1,ret);
    }
    void work()
    {
       scanf("%d",&n);
       for(int i=1;i<=n;i++){
          scanf("%d",&fa[i]);
          if(fa[i])link(fa[i],i),link(i,fa[i]);
       }
       scanf("%d",&m);
       int flag;
       for(int i=1;i<=m;i++){
          scanf("%d",&flag);
          if(flag==1){
             mt++;scanf("%d%d%d",&q[mt].x,&q[mt].y,&q[mt].c);
             q[mt].c=i-q[mt].c-1;
          }
          else scanf("%d",&tx[i]);
       }
       dep[1]=1;dfs1(1);dfs2(1,1);
       for(int i=1;i<=m;i++){
          if(!tx[i])root[i]=root[i-1];
          else updata(root[i],root[i-1],1,n,id[tx[i]]);
       }
       for(int i=1;i<=mt;i++)
          solve(q[i].x,q[i].y,q[i].c);
    }
    
    int main()
    {
    	work();
    	return 0;
    }
    
    
  • 相关阅读:
    php面试题
    php最基本的缓存之一页面缓存
    原生PHP生成验证码
    原生PHP实现上传大图片与缩略图
    PHP实现连接数据库下载与导入csv格式文件
    ScrollTop火狐谷歌不兼容
    今天学的是 HTML基本元素、基本语法元素特点等,就发图片吧。
    第三天的学习知识HTML5常用的重要单词
    第二天学习了设计方面的知识
    HTLM5第一天的内容
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7607555.html
Copyright © 2011-2022 走看看