• BZOJ4196 [NOI2015] 软件包管理器


    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4196http://uoj.ac/problem/128

    Description

    Linux用户和OSX用户一定对软件包管理器不会陌生。通过软件包管理器,你可以通过一行命令安装某一个软件包,然后软件包管理器会帮助你从软件源下载软件包,同时自动解决所有的依赖(即下载安装这个软件包的安装所依赖的其它软件包),完成所有的配置。Debian/Ubuntu使用的apt-get,Fedora/CentOS使用的yum,以及OSX下可用的homebrew都是优秀的软件包管理器。

    你决定设计你自己的软件包管理器。不可避免地,你要解决软件包之间的依赖问题。如果软件包A依赖软件包B,那么安装软件包A以前,必须先安装软件包B。同时,如果想要卸载软件包B,则必须卸载软件包A。现在你已经获得了所有的软件包之间的依赖关系。而且,由于你之前的工作,除0号软件包以外,在你的管理器当中的软件包都会依赖一个且仅一个软件包,而0号软件包不依赖任何一个软件包。依赖关系不存在环(若有m(m≥2)个软件包A1,A2,A3,…,Am,其中A1依赖A2,A2依赖A3,A3依赖A4,……,Am−1依赖Am,而Am依赖A1,则称这m个软件包的依赖关系构成环),当然也不会有一个软件包依赖自己。
    现在你要为你的软件包管理器写一个依赖解决程序。根据反馈,用户希望在安装和卸载某个软件包时,快速地知道这个操作实际上会改变多少个软件包的安装状态(即安装操作会安装多少个未安装的软件包,或卸载操作会卸载多少个已安装的软件包),你的任务就是实现这个部分。注意,安装一个已安装的软件包,或卸载一个未安装的软件包,都不会改变任何软件包的安装状态,即在此情况下,改变安装状态的软件包数为0。

    Input

    输入文件的第1行包含1个正整数n,表示软件包的总数。软件包从0开始编号。

    随后一行包含n−1个整数,相邻整数之间用单个空格隔开,分别表示1,2,3,…,n−2,n−1号软件包依赖的软件包的编号。
    接下来一行包含1个正整数q,表示询问的总数。
    之后q行,每行1个询问。询问分为两种:
    installx:表示安装软件包x
    uninstallx:表示卸载软件包x
    你需要维护每个软件包的安装状态,一开始所有的软件包都处于未安装状态。对于每个操作,你需要输出这步操作会改变多少个软件包的安装状态,随后应用这个操作(即改变你维护的安装状态)。

    Output

    输出文件包括q行。

    输出文件的第i行输出1个整数,为第i步操作中改变安装状态的软件包数。
     

    听说这是NOI题目?水水的树链剖分

    建立一棵有向树,边由被依赖的软件包指向依赖的软件包

    安装一个软件包就从根到这个点的一条链全部改为1,卸载一个软件包就把它的子树全部改为0

    根据DFS序的性质,如果一个点在线段树上的编号为 pos[x],子树的最后一个节点的编号就为 pos[x] + size[x] - 1,在线段树上这棵子树是连续的一个区间

    软件包的编号从0开始,所以对所有的点都加了一个偏移量1

    第一次交的时候打成了 pos[x + size[x] - 1],导致了RE,还有其他的一些bug,出现后从UOJ上找来样例数据

    BZOJ的数据太夸张了,UOJ才3317ms

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <algorithm>
      4 #include <cstring>
      5 #define rep(i,l,r) for(int i=l; i<=r; i++)
      6 #define clr(x,y) memset(x,y,sizeof(x))
      7 #define travel(x) for(Edge *p=last[x]; p; p=p->pre)
      8 using namespace std;
      9 const int INF = 0x3f3f3f3f;
     10 const int maxn = 100010;
     11 inline int read(){
     12     int ans = 0, f = 1;
     13     char c = getchar();
     14     for(; !isdigit(c); c = getchar())
     15     if (c == '-') f = -1;
     16     for(; isdigit(c); c = getchar())
     17     ans = ans * 10 + c - '0';
     18     return ans * f;
     19 }
     20 struct Edge{
     21     Edge *pre; int to;
     22 }edge[maxn<<1];
     23 Edge *last[maxn], *pt = edge;
     24 struct Node{
     25     int l,r,v,t;
     26 }t[maxn<<2];
     27 int n,m,x,y,q,segnum=0,dep[maxn],top[maxn],size[maxn],fa[maxn],pos[maxn];
     28 char ch[10];
     29 inline void addedge(int x,int y){
     30     pt->pre = last[x]; pt->to = y; last[x] = pt++;
     31 }
     32 void dfs(int x){
     33     size[x] = 1;
     34     travel(x){
     35         dep[p->to] = dep[x] + 1;
     36         fa[p->to] = x;
     37         dfs(p->to);
     38         size[x] += size[p->to];
     39     }
     40 }
     41 void dfs(int x,int chain){
     42     pos[x] = ++segnum; top[x] = chain;
     43     int k = 0;
     44     travel(x){
     45         if (size[p->to] > size[k]) k = p->to;
     46     }
     47     if (!k) return;
     48     dfs(k,chain);
     49     travel(x){
     50         if (p->to != k) dfs(p->to,p->to);
     51     }
     52 }
     53 void build(int u,int v,int w){
     54     t[w].l = u; t[w].r = v; t[w].v = 0; t[w].t = -1;
     55     if (u == v) return;
     56     int mid = (u + v) >> 1;
     57     build(u,mid,w<<1); build(mid+1,v,w<<1|1);
     58 }
     59 inline void pushdown(int w){
     60     if (t[w].l == t[w].r || t[w].t == -1) return;
     61     t[w<<1].t = t[w<<1|1].t = t[w].t;
     62     t[w<<1].v = (t[w<<1].r - t[w<<1].l + 1) * t[w].t;
     63     t[w<<1|1].v = (t[w<<1|1].r - t[w<<1|1].l + 1) * t[w].t;
     64     t[w].t = -1;
     65 }
     66 inline void maintain(int w){
     67     t[w].v = t[w<<1].v + t[w<<1|1].v;
     68 }
     69 void modify(int u,int v,int w,int x){
     70     pushdown(w);
     71     if (t[w].l == u && t[w].r == v){
     72         t[w].v = x * (v - u + 1);
     73         t[w].t = x; return;
     74     }
     75     int mid = (t[w].l + t[w].r) >> 1;
     76     if (v <= mid) modify(u,v,w<<1,x);
     77     else if (u > mid) modify(u,v,w<<1|1,x);
     78     else{
     79         modify(u,mid,w<<1,x);
     80         modify(mid+1,v,w<<1|1,x);
     81     }
     82     maintain(w);
     83 }
     84 int query(int u,int v,int w){
     85     pushdown(w);
     86     if (t[w].l == u && t[w].r == v) return t[w].v;
     87     int mid = (t[w].l + t[w].r) >> 1;
     88     if (v <= mid) return query(u,v,w<<1);
     89     else if (u > mid) return query(u,v,w<<1|1);
     90     else return query(u,mid,w<<1) + query(mid+1,v,w<<1|1);
     91 }
     92 int install(int x,int y){
     93     int ret = 0;
     94     while (top[x] != top[y]){
     95         if (dep[top[x]] < dep[top[y]]) swap(x,y);
     96         ret += query(pos[top[x]],pos[x],1);
     97         modify(pos[top[x]],pos[x],1,1);
     98         x = fa[top[x]];
     99     }
    100     if (dep[x] < dep[y]) swap(x,y);
    101     ret += query(pos[y],pos[x],1);
    102     modify(pos[y],pos[x],1,1);
    103     return ret;
    104 }
    105 int uninstall(int x){
    106     int ret = query(pos[x],pos[x]+size[x]-1,1);
    107     modify(pos[x],pos[x]+size[x]-1,1,0);
    108     return ret;
    109 }
    110 int main(){
    111     n = read(); clr(last,0);
    112     rep(i,1,n-1){
    113         x = read();
    114         addedge(x+1,i+1);
    115     }
    116     dep[1] = 0; dfs(1); dfs(1,1); build(1,n,1);
    117     q = read();
    118     rep(i,1,q){
    119         scanf("%s",ch); x = read() + 1;
    120         if (ch[0] == 'i') printf("%d
    ",dep[x] + 1 - install(1,x));
    121         else printf("%d
    ",uninstall(x));
    122     }
    123     return 0;
    124 }
    View Code
  • 相关阅读:
    将项目发布到多台服务器并解决高并发
    Nginx 反向代理和负载均衡
    Nginx的基本理论
    图片上传功能(EasyUI前台框架+SSM框架)
    错误:Eclipse老是出现 updating error reports database
    JPA
    Java中 @override 报错
    SpringBoot常用注解
    SpringBoot学习:整合shiro(rememberMe记住我后自动登录session失效解决办法)
    SpringBoot学习:整合shiro(rememberMe记住我功能)
  • 原文地址:https://www.cnblogs.com/jimzeng/p/bzoj4196.html
Copyright © 2020-2023  润新知