P2146 [NOI2015] 软件包管理器

P2146 [NOI2015] 软件包管理器

题意:

如果软件包 a 依赖软件包 b,那么安装软件包 a 以前,必须先安装软件包 b。同时,如果想要卸载软件包 b,则必须卸载软件包 a。
软件包之间存在依赖关系,除了0号软件包以外,其他软件包都会依赖一个且仅一个软件包。不会存在环的情况
现在对某个软件包进行安装和卸载,问这个操作实际上会改变多少个软件包的安装状态

题解:

本质就两个操作,安装是询问节点x到根节点的操作,卸载是查询x的子树的操作。但是题目中问的是每一步操作会改变多少状态,所以我们需要记录上一次的状态,然后操作完后得到现在的状态,差的绝对值就是本次操作的答案

代码:

#include<bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define full(a,b) memset(a,b,sizeof a)
#define N 100005
int n,q;
int head[N],ecnt,nxt[N],to[N];
int dad[N],son[N],dep[N],size[N];
int top[N],id[N],rev[N];
int last,s[4*N],lazy[4*N];
void init()//初始化 
{full(head,-1);full(lazy,-1);
}
int read()//快读 
{int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar();while(ch>='0'&&ch<='9') x=10*x+ch-'0',ch=getchar();return x*f;
}
void add(int u,int v)//增加结点 
{to[++ecnt]=v;nxt[ecnt]=head[u];head[u]=ecnt;
}
void pre(int u,int fa)//求深度,子结点等 
{dep[u]=dep[fa]+1;dad[u]=fa;size[u]=1;for(int i=head[u]; i!=-1; i=nxt[i]){int v=to[i];if(v==fa) continue;pre(v,u);size[u]+=size[v];if(size[v]>size[son[u]]) son[u]=v;}
}
void dfsx(int u)//求链 
{int v=son[u];if(v){id[v]=++id[0];rev[id[0]]=v;top[v]=top[u];dfsx(v);}for(int i=head[u]; i!=-1; i=nxt[i]){v=to[i];if(top[v]) continue;id[v]=++id[0];rev[id[0]]=v;top[v]=v;dfsx(v);}
}
void pushdown(int k,int l,int r)//传递lazy标记 
{if(lazy[k]==-1) return;int mid=(l+r)>>1;lazy[2*k]=lazy[2*k+1]=lazy[k];s[2*k]=(mid-l+1)*lazy[k];s[2*k+1]=(r-mid)*lazy[k];lazy[k]=-1;
}
void update(int k,int l,int r,int x,int y,int v)//区间修改模板 
{if(x>r||y<l) return;if(x<=l&&r<=y){s[k]=v*(r-l+1);lazy[k]=v;return;}int mid=(l+r)>>1;pushdown(k,l,r);update(k*2,l,mid,x,y,v);update(k*2+1,mid+1,r,x,y,v);s[k]=s[2*k]+s[2*k+1];
}
void query(int u,int v)//询问u->v的路径 
{int fu=top[u],fv=top[v];while(fu!=fv){if(dep[fu]<dep[fv]) swap(u,v),swap(fu,fv);update(1,1,n,id[fu],id[u],1);u=dad[fu];fu=top[u];}if(dep[u]>dep[v]) swap(u,v);update(1,1,n,id[u],id[v],1);
}
int main()
{init();n=read();for(int i=2; i<=n; i++){int x=read()+1;//下标从1开始 add(x,i);}pre(1,0);id[1]=++id[0];rev[1]=1;top[1]=1;dfsx(1);///造链 q=read();for(int i=1; i<=q; i++){char flag[15];scanf("\n%s",flag);int x=read()+1;//下标从1开始 if(flag[0]=='i') query(1,x);//询问x到根节点 else update(1,1,n,id[x],id[x]+size[x]-1,0);//删除子树 printf("%d\n",abs(last-s[1]));//输出差的绝对值 last=s[1];//更新结点数 }return 0;
}

重温一遍,每次修改完值与上一次进行比较

#include<cstdio>
#include<cstring>
#include<algorithm>
const int maxn=200005;
int n,k=0,x,head[maxn],q,deep[maxn],father[maxn],size[maxn];
int tid[maxn],top[maxn],son[maxn],tidnum=0,pos[maxn];char s[15];
struct node
{int to,next;
} edge[maxn<<1];
struct Node
{int left,right,flag,sum;
} tree[maxn<<2];
void add(int u,int v)
{edge[++k].to=v;edge[k].next=head[u];head[u]=k;
}
int read()
{int x=0;char ch=getchar();while(ch<48||ch>57) ch=getchar();while(ch>=48&&ch<=57) x=x*10+ch-48,ch=getchar();return x;
}
void dfs1(int x,int fa,int depth)
{size[x]=1;father[x]=fa;deep[x]=depth;for(int i=head[x];i;i=edge[i].next){if(edge[i].to==fa) continue;dfs1(edge[i].to,x,depth+1);size[x]+=size[edge[i].to];if(!son[x]||size[edge[i].to]>size[son[x]]) son[x]=edge[i].to;}
}
void dfs2(int x,int tp)
{tid[x]=++tidnum;pos[tid[x]]=x;top[x]=tp;if(!son[x]) return;dfs2(son[x],tp);for(int i=head[x];i;i=edge[i].next){if(edge[i].to!=son[x]&&edge[i].to!=father[x])dfs2(edge[i].to,edge[i].to);}
}
void build(int id,int l,int r)
{tree[id].left=l;tree[id].right=r;tree[id].sum=0;tree[id].flag=-1;if(l==r) return;int mid=(l+r)>>1;build(id<<1,l,mid);build(id<<1|1,mid+1,r);return;
}
void downdata(int id)
{tree[id<<1].sum=(tree[id<<1].right-tree[id<<1].left+1)*tree[id].flag;tree[id<<1|1].sum=(tree[id<<1|1].right-tree[id<<1|1].left+1)*tree[id].flag;tree[id<<1].flag=tree[id<<1|1].flag=tree[id].flag;tree[id].flag=-1;
}
int get(int id,int l,int r)
{if(tree[id].right<l||tree[id].left>r) return 0;if(tree[id].right<=r&&tree[id].left>=l) return tree[id].sum;if(tree[id].flag!=-1) downdata(id);return get(id<<1,l,r)+get(id<<1|1,l,r);
}
void update(int id,int l,int r,int val)
{if(tree[id].right<l||tree[id].left>r) return;if(tree[id].right<=r&&tree[id].left>=l){tree[id].sum=(tree[id].right-tree[id].left+1)*val;tree[id].flag=val;return;}if(tree[id].flag!=-1) downdata(id);update(id<<1,l,r,val);update(id<<1|1,l,r,val);tree[id].sum=tree[id<<1].sum+tree[id<<1|1].sum;return;
}
void change(int u,int v,int val)
{while(top[u]!=top[v]){if(deep[top[u]]<deep[top[v]]) std::swap(u,v);update(1,tid[top[u]],tid[u],val);u=father[top[u]];}if(deep[u]>deep[v]) std::swap(u,v);update(1,tid[u],tid[v],val);return;
}
int main()
{n=read();for(int i=2;i<=n;i++){x=read();x++;add(x,i);}dfs1(1,1,1);dfs2(1,1);q=read();build(1,1,tidnum);for(int i=1;i<=q;i++){scanf("%s",s);x=read();x++;int t1=tree[1].sum;if(s[0]=='i'){change(1,x,1);//1到x权值变成1 int t2=tree[1].sum;printf("%d\n",abs(t2-t1));}if(s[0]=='u'){update(1,tid[x],tid[x]+size[x]-1,0);//1到x权值变成0 int t2=tree[1].sum;printf("%d\n",abs(t1-t2));}}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/318199.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微软 2018 开源大事记

从微软公开宣布 "Microsoft love linux" 那一刻起&#xff0c;过去的几年里&#xff0c;微软积极拥抱开源的举动我们有目共睹&#xff0c;即便有过"Linux is a cancer"这种真香警告的 flag&#xff0c;但不得不承认的是&#xff0c;微软一系列“拥抱开源”…

模板:二叉搜索树平衡树

文章目录前言二叉搜索树代码treap代码splay开点旋转splay插入查找第k大元素查找给定元素的排名前驱&后继删除完整代码练习总结前言 终于开始学这个东西了 看了好几篇博客才找到一篇可读的qwq 我曾经还以为线段树码量大…我真傻&#xff0c;真的 所谓平衡树&#xff0c;就是…

51nod2626-未来常数【树上启发式合并,线段树】

正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId2626 题目大意 给出nnn个点的一棵树&#xff0c;每个区间[l,r][l,r][l,r]的代价是选出这个区间中的一个点xxx使得它走到所有点然后又回到xxx的路程最短长度&#xff0c;求一个随机区间的期望代价。 1≤n…

A*,IDA*—高档次的暴搜

A*通过评价函数来判断当前状态是否可以到达最终状态(即可行性剪枝)&#xff0c;来减少不必要的搜索。 例题——P2324 [SCOI2005]骑士精神 我们通过当前不在指定位置上的棋子个数为评价函数&#xff0c;\(used\) 【评价函数值】超过了预期的值&#xff0c;便不用再线下深入搜索了…

P2486 [SDOI2011]染色

P2486 [SDOI2011]染色 题意&#xff1a; 题解&#xff1a; 与一般的树链剖分相比&#xff0c;不同点在于查询的不是路径上颜色的数量而是颜色段的数量 对于两个颜色段&#xff0c;112和221&#xff0c;两个颜色段数量都是2 如果合在一起颜色段的数量就是3&#xff0c;因为左边…

牛客网CSP-S提高组赛前集训营1题解(仓鼠的石子游戏 [博弈论] + 乃爱与城市的拥挤程度 [树上DP] + 小w的魔术扑克[dfs + 离线])

文章目录T1&#xff1a;仓鼠的石子游戏题目题解代码实现T2&#xff1a;乃爱与城市拥挤程度题目题解代码实现T3&#xff1a;小w的魔术扑克题目题解代码实现T1&#xff1a;仓鼠的石子游戏 题目 仓鼠和兔子被禁止玩电脑&#xff0c;无聊的他们跑到一块空地上&#xff0c;空地上有…

使用PerfView监测.NET程序性能(二):Perfview的使用

在上一篇博客使用PerfView监测.NET程序性能&#xff08;一&#xff09;&#xff1a;Event Trace for Windows 中&#xff0c;我们了解了对Windows及应用程序进行性能分析的基础&#xff1a;Event Trace for Windows (ETW)。现在来看看基于ETW的性能分析工具——Perfview.exePer…

连通性相关

强联通分量 强连通&#xff1a;有向图 \(G\) 强连通表示&#xff0c;\(G\) 中任意两个结点连通。 强连通分量( Strongly Connected Components &#xff0c;简称 \(\operatorname{SCC}\) )&#xff1a;极大的 强连通子图。 Tarjan 维护了以下两个变量&#xff1a; \(dfn\) &…

CF505E-Mr. Kitayuta vs. Bamboos【贪心,二分】

正题 题目链接:https://www.luogu.com.cn/problem/CF505E 题目大意 开始一个长度为nnn的序列hhh&#xff0c;mmm天每天你可以kkk次选择一个hih_ihi​让它等于himax{hi−p,0}h_imax\{h_i-p,0\}hi​max{hi​−p,0}&#xff0c;然后结束时让每个hihiaih_ih_ia_ihi​hi​ai​&…

阶段总结:8.09-8.18 十日模拟

一图流了解一下 文章目录十日谈总结十日谈 再总结一下 8.09 搜索模拟&#xff1a;25分。…毕竟是第一天不太适应吧 &#xff08;拼命找借口&#xff09;。没有看到标题就很淦&#xff0c;就是全写挂了而已&#xff0c;已经无从谈起…hzwer的粉丝那题提醒我们不要被吓人的数据…

学习有向图和无向图的强连通分量(基本概念+割点+点双联通分量+桥+边双连通分量+全套模板【Tarjan】)

最近总是考到Tarjan&#xff0c;让我措手不及基本概念割点以及点双连通分量Tarjan法求割点推导过程代码实现Tarjan法求点双连通分量推导过程代码实现有向图的Tarjan缩点桥与边双连通分量Tarjan法求桥理论推导代码实现Tarjan法求边双连通分量理论推导代码实现前言&#xff1a;有…

.NET Core下的Spring Cloud——前言和概述

前言前几年一直在写类似dubbo&#xff0c;Spring Cloud的微服务框架辗辗转转重复了多次&#xff0c;也重构推翻了很多次&#xff0c;其中诞生了“Rabbit.Rpc”,”Go”,”RabbitCloud”等开源项目。其中不乏他人对这些项目的完善。很高兴自己的开源项目能够给他人提供思路和复用…

期望 概率DP

期望 \(x\) 的期望 \(E(x)\) 表示平均情况下 \(x\) 的值。 令 \(C\) 表示常数&#xff0c; \(X\) 和 \(Y\) 表示两个随机变量。 \(E(C)C\) \(E(C \times X)C \times E(X)\) \(E(XY)E(X)E(Y)\) 期望的线性性 \(E(XY)\) 不一定等于 \(E(X) \times E(Y)\) 期望练习&#xff1a…

CF785E Anton and Permutation

CF785E Anton and Permutation 题意&#xff1a; 对于一个长度为 n 的序列进行 k 次操作&#xff0c;每次操作都是交换序列中的某两个数。对于每一个操作&#xff0c;回答当前序列中有多少个逆序对。 1<n<200000 1<q<50000 题解&#xff1a; 动态逆序对&#x…

P5311-[Ynoi2011]成都七中【点分树,树状数组】

正题 题目链接:https://www.luogu.com.cn/problem/P5311 题目大意 给出nnn个点的一棵树&#xff0c;每个节点有一个颜色&#xff0c;mmm次询问提出区间[l,r][l,r][l,r]的点构成的生成子图中xxx所在连通块的颜色数。 1≤n,m,ai≤1051\leq n,m,a_i\leq 10^51≤n,m,ai​≤105 解…

[ NOIP提高组 2016]愤怒的小鸟(暴搜 + 状压DP)// [SNOI2017]一个简单的询问(莫队)

一次性写两道题T1&#xff1a;一个简单的询问题目题解代码实现T2&#xff1a;愤怒的小鸟题目暴搜题解暴搜代码实现状压DP题解状压DP代码实现T1&#xff1a;一个简单的询问 题目 给你一个长度为 N 的序列 ai ,1≤i≤N&#xff0c;和 q 组询问&#xff0c;每组询问读入 l1,r1,l…

微软发布新的 Azure Pipelines 功能和集成

在最近举行的Connect()大会上&#xff0c;微软发布了几项新功能以及与 Azure Pipelines 的集成&#xff0c;包括 Visual Studio Code 的 Azure Pipelines 扩展、GitHub 版本管理、对 IoT 项目的支持以及 ServiceNow 集成。自从 9 月份推出 Azure Pipelines 以来&#xff0c;这种…

平衡树练习总结

文章目录前言普通平衡树文艺平衡树郁闷的出纳员书架宠物收养场机械排序千山鸟飞绝总结前言 专门刷了一天半的平衡树 &#xff08;附带划水OvO&#xff09; 使用的是蜜汁常数的splay 感觉对平衡树的理解还是有帮助的 一些较为常规的平衡树的题应该是差不多了 更正之前刚学的观点…

二维树状数组

二维树状数组可以实现在平面上的区域加、区域查询等操作。 区域修改 我们在一维时维护树状数组的区间操作时&#xff0c;对其进行了差分。类比一维的思想&#xff0c;我们在二维平面上也对树状数组差分。 我们来看二维的前缀和&#xff1a; \[sum(i,j)sum(i-1,j)sum(i,j-1)-sum…

【AcWing 249. 蒲公英】

【AcWing 249. 蒲公英】 题意&#xff1a; 长度为n的序列&#xff0c;给定区间&#xff0c;求区间众数&#xff0c;如果出现次数相同&#xff0c;输出编号最小的 题解&#xff1a; 区间众数&#xff0c;不带修改&#xff0c;强制在线&#xff08;否则可以莫队&#xff09; …