CodeForces - 571D Campus(数据结构综合)
题目链接:点击查看
题目大意:
题目分析:数据结构的题目写起来真好玩~(debug到吐)
考虑离线,题目实质上就是维护两个森林,然后对同一个序列进行的赋值操作,如果是对单一的森林进行加边删边然后连通块内求值修改之类的话,不难想到克鲁斯卡尔重构树,但两个森林的话该怎么办呢
注意到第一个森林中对连通块的操作是加法,第二个森林中对连通块的操作是置零
任取一个点 x 进行讨论,假设现在不考虑第二个森林的贡献,也就是忽略掉第二种操作和第四种操作,并且在每次操作后都记录一下点 x 的值,更具体的,设 val_x[ i ] 是在经过第 i 个操作后,点 x 的值
现在假设第 r 个操作是 “ Q x ”,也就是在第 r 个操作时需要输出 x 的值,但并不是需要输出 val_x[ r ] ,因为 val_x 记录的只是第一个森林的贡献,为了计算总贡献,我们需要知道在第 r 个操作之前,对于点 x 来说距离最近的一次操作 4,也就是第二个森林的置零操作,找到的这个位置记为 l,换句话说,现在在第 l 个操作时将点 x 置零,需要输出第 r 个操作时 x 的值,也就是说在闭区间 [ l + 1 , r ] 内 val_x 的值只受到了第一个森林的影响,到此为止不难想到答案就是 val_x[ r ] - val_x[ l ] 了
综上所述,我们将问题又进行了进一步的转换:
- 先通过第二个森林求出每一个操作 Q x 的可行区间 [ l , r ] ,满足:
- 当前的操作 Q x 是第 r 次操作
- 第 l 次操作是对于点 x 进行的置零操作
- 闭区间 [ l + 1 , r ] 内再无对于点 x 进行的置零操作
- 再通过第二个森林去维护每个点的 val_x,对于一个操作 Q x 来说,其通过上述操作求出的区间为 [ l , r ] ,那么在其 l 位置减去 val_x[ l ],在其 r 位置减去 val_x[ r ] 就是操作 Q x 的答案
这样就将第一个森林和第二个森林各自的作用区分开来,转换成了两个独立的森林提供的贡献
剩下的用克鲁斯卡尔重构树乱搞就好了
代码:
//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<unordered_map>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e6+100;char op[N][2];int n,m,a[N];LL ans[N];vector<int>q[N];struct Ex_Kruskal
{int f[N],L[N],R[N],sz[N],tot,index;vector<int>node[N];void init(int n){tot=0;index=n;for(int i=0;i<=n<<1;i++)f[i]=i;}int find(int x){return f[x]==x?x:f[x]=find(f[x]);}void addedge(int x,int y){int xx=find(x),yy=find(y);if(xx!=yy){f[xx]=f[yy]=++index;node[index].push_back(xx);node[index].push_back(yy);}}void dfs(int u){L[u]=++tot;sz[u]=(u<=n);for(auto v:node[u]){dfs(v);sz[u]+=sz[v];}R[u]=tot;}
};struct Set1
{Ex_Kruskal kru;int n;struct Node{int l,r;LL sum;}tree[N<<2];void get_dfs(){n=kru.index;for(int i=1;i<=n;i++)if(kru.find(i)==i)kru.dfs(i);}void pushdown(int k){if(tree[k].sum){tree[k<<1].sum+=tree[k].sum;tree[k<<1|1].sum+=tree[k].sum;tree[k].sum=0;}}void build(int k,int l,int r){tree[k].l=l;tree[k].r=r;tree[k].sum=0;if(l==r)return;int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);}void update(int k,int l,int r,int val){if(tree[k].l>r||tree[k].r<l)return;if(tree[k].l>=l&&tree[k].r<=r){tree[k].sum+=val;return;}pushdown(k);update(k<<1,l,r,val);update(k<<1|1,l,r,val);}void change(int x){update(1,kru.L[a[x]],kru.R[a[x]],kru.sz[a[x]]);}LL query(int k,int pos){if(tree[k].l==tree[k].r)return tree[k].sum;pushdown(k);int mid=tree[k].l+tree[k].r>>1;if(pos<=mid)return query(k<<1,pos);elsereturn query(k<<1|1,pos);}LL ask(int x){return query(1,kru.L[a[x]]);}
}t1;struct Set2
{Ex_Kruskal kru;int n;struct Node{int l,r;int time;}tree[N<<2];void get_dfs(){n=kru.index;for(int i=1;i<=n;i++)if(kru.find(i)==i)kru.dfs(i);}void pushdown(int k){if(tree[k].time){tree[k<<1].time=tree[k<<1|1].time=tree[k].time;tree[k].time=0;}}void build(int k,int l,int r){tree[k].l=l;tree[k].r=r;tree[k].time=0;if(l==r)return;int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);}void update(int k,int l,int r,int val){if(tree[k].l>r||tree[k].r<l)return;if(tree[k].l>=l&&tree[k].r<=r){tree[k].time=val;return;}pushdown(k);update(k<<1,l,r,val);update(k<<1|1,l,r,val);}void change(int x){update(1,kru.L[a[x]],kru.R[a[x]],x);}int query(int k,int pos){if(tree[k].l==tree[k].r)return tree[k].time;pushdown(k);int mid=tree[k].l+tree[k].r>>1;if(pos<=mid)return query(k<<1,pos);elsereturn query(k<<1|1,pos);}int ask(int x){return query(1,kru.L[a[x]]);}
}t2;int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);scanf("%d%d",&n,&m);t1.kru.init(n),t2.kru.init(n);for(int i=1,x,y;i<=m;i++){scanf("%s%d",op[i],&x);switch(op[i][0]){case 'U':scanf("%d",&y);t1.kru.addedge(x,y);break; case 'M':scanf("%d",&y);t2.kru.addedge(x,y);break;case 'A':a[i]=t1.kru.find(x);break;case 'Z':a[i]=t2.kru.find(x);break;case 'Q':a[i]=x;break;}}t1.get_dfs(),t2.get_dfs();t1.build(1,1,t1.n),t2.build(1,1,t2.n);for(int i=1;i<=m;i++){switch(op[i][0]){case 'Z':t2.change(i);break;case 'Q':q[t2.ask(i)].push_back(i);break;}}for(int i=1;i<=m;i++){switch(op[i][0]){case 'A':t1.change(i);break;case 'Z':for(auto it:q[i])ans[it]-=t1.ask(it);break;case 'Q':ans[i]+=t1.ask(i);break;}}for(int i=1;i<=m;i++)if(op[i][0]=='Q')printf("%lld\n",ans[i]);return 0;
}
CodeForces - 571D Campus(数据结构综合)相关推荐
- 实验五 数据结构综合应用 20162305
实验五 数据结构综合应用 20162305 0 分析系统架构 我们本次做的是一个飞机大战的游戏,本次游戏是想让使用者通过操控一个飞机进行击毁敌机和躲避敌机的操作.这个APP总体是基于精灵类ISpirt ...
- 20162316刘诚昊 实验五-数据结构综合应用
20162316刘诚昊 2017-2018-2 <Java程序设计>第五次实验 数据结构综合应用 实验链接: 实验五 Android Studio遇到的错误-1 实验五 图的实现与应用-2 ...
- 408数据结构综合题
数据结构综合应用题⑩ 试证明:若借助栈可由输入序列1,2,3,-n得到一个输出序列p1,p2,p3,-pn(它是输入序列的某一种排列),则在输出序列中不可能出现以下情况:存在i<j<k,使 ...
- BUAA-2021春-数据结构-综合作业-文本摘要生成(Hash实现 + SIMD优化 终测最速)
题目内容 问题描述 在自然语言文本处理中,有一种分析文本.自动抽取文本主题思想的方法(通常用于文本摘要生成),其方法如下: 1. 首先分析文本中非停用词(stop-word)的出现频度: ...
- 数据结构Java版实验五_实验五数据结构综合应用 20162310
分析系统架构 Sprite精灵类 ISprite精灵类是所有类的父类 CombatAircraft战斗机类 首先确保战斗机完全位于Canvas范围内,每隔7帧发射单发黄色子弹. protected v ...
- 武汉理工大学数据结构综合实验——二叉树与赫夫曼图片压缩
文章目录 实验目的 主要仪器设备及耗材 一.实验要求 二.分析与设计 1.数据结构的设计 2.核心算法设计 生成Huffman树的算法 生成Huffman编码的算法 压缩编码的算法 3.测试用例设计 ...
- 武汉理工大学数据结构综合实验——图与景区信息管理系统实践
文章目录 实验目的 主要仪器设备及耗材 一.实验要求 二.分析与设计 1.数据结构的设计 2.核心算法设计 改进DFS算法 搜索最短路径 Prim算法(构建最小生成树) 3.测试用例设计 4.测试结果 ...
- 武汉理工大学数据结构综合实验——连连看游戏综合实践
文章目录 实验目的 主要仪器设备及耗材 一.实验要求 二.分析与设计(非线性结构) 1.数据结构的设计 2.核心算法设计 一条直线消子 两条直线消子 三条直线消子 初始化游戏地图 搜寻路径 提示和重排 ...
- 大话备考之数据结构综合题
综合题 题型1 深度优先遍历与广度优先遍历 1.已知二维数组表示的图的邻接矩阵如下图所示.试分别给出深度优先和广度优先遍历序列,并画出自顶点1出发进行遍历所得的深度优先生成树和广度优先生成树. 首先看 ...
最新文章
- 行业观察 | 全球IoT云平台第一股诞生,IoT离爆发还有多远?
- 为什么要使用符号作为hash的键
- VS2019编写简单的C程序示例
- string 转 int_面试官:String长度有限制吗?是多少?还好我看过
- SpringSecurity3.0.4的An AuthenticationManager is...
- C语言俄罗斯方块代码(成功版)
- 大数据之路之交通大数据应用总体架构设计
- wav音频文件格式解析【个人笔记】(自用)
- Windows android adb interface驱动安装失败 ADB interface驱动安装失败解决方法
- 华硕Android原始密码,华硕(ASUS)路由器默认密码是多少? | 192路由网
- 刨根问底 | 红遍全网的SD-WAN,到底是个啥?
- android 大众点评,Android 大众点评的接入
- python开发小程序拼团_【微擎微赞模块】砍价宝4.5小程序版+小程序前端+后端+素材包+砍价+抢购+拼团...
- 30岁之后想转行,可行吗?这20条建议让你少走弯路!
- 逻辑英语——动词和分词-----名词
- html创建电子邮件链接教程
- iMeta高被引论文|西农焦硕/韦革宏等-干旱生态系统中土壤真菌与细菌群落构建的关系...
- Android 连接USB设备(主机模式)
- JavaScript小练习-计算银行卡余额案例
- 十年前的AlexNet,今天的NeurIPS 2022时间检验奖