题目:

题目背景

SCOI2011 DAY2 T1

题目描述

有 N 个节点,标号从 1 到 N ,这 N 个节点一开始相互不连通。第i个节点的初始权值为 a[i] ,接下来有如下一些操作:
U x y:     加一条边,连接第 x 个节点和第 y 个节点
A1 x v:    将第 x 个节点的权值增加 v
A2 x v:    将第 x 个节点所在的连通块的所有节点的权值都增加 v
A3 v:      将所有节点的权值都增加 v
F1 x:      输出第 x 个节点当前的权值
F2 x:      输出第 x 个节点所在的连通块中,权值最大的节点的权值
F3:        输出所有节点中,权值最大的节点的权值

输入格式

输入的第一行是一个整数 N ,代表节点个数。
接下来一行输入 N 个整数,a[1], a[2], …, a[N],代表 N 个节点的初始权值。
再下一行输入一个整数 Q ,代表接下来的操作数。
最后输入 Q 行,每行的格式如题目描述所示。

输出格式

对于操作 F1, F2, F3,输出对应的结果,每个结果占一行。

样例数据 1

输入  [复制]

 


0 0 0 

A1 3 -20 
A1 2 20 
U 1 3 
A2 1 10 
F1 3 
F2 3 
A3 -10 
F3

输出

-10 
10 
10

备注

【数据范围】
对于 30% 的数据,保证 N<=100,Q<=10000
对于 80% 的数据,保证 N<=100000,Q<=100000
对于 100% 的数据,保证 N<=300000,Q<=300000
对于所有的数据,保证输入合法,并且 -1000<=v, a[1], a[2], …, a[N]<=1000

题解:

这道题可以用可并堆或者线段树来写····

然而如果用可并堆得话得会删除特定的点的操作··然而··我一直认为如果有删除特定的点的操作还不如用splay···

然后我就打了2个小时的splay····最后写不出来弃疗了·····这道题用可并堆做出来的人是真正的勇士·····

也从这道题中发现了自己代码能力的不足··一是粗心大意···二是不懂得简化代码··搞得写到最后脑袋发蒙·····以后多看看那些写得简洁的人的代码····

然后我就用线段树来写了··下面将线段树的方法:

其实用线段树写的话最重要的是要维护一个dfs序···在我们进行离线操作后dfs出来的dfs序必须保证:任意时间所有在同一个并查集里的点的dfs序是连续的···

怎么做到呢?有两点:

第一点:我们离线时侯的建边的顺序必须是和我们在离线后dfs时的顺序是一致的

打个比方···题目中先是连1,2的边··后连1,3的边··那么我们在dfs时候必须先走1,2的边····

要做到这一点很简单··考虑到临接表加边的顺序与dfs时的顺序是反的···因此我们每次不直接加边··先将边保存起来···最后将所有边倒着加入即可······

第二点:dfs顺序必须和加边的顺序一致

依然举上面的例子···如果我们连了2,1的边···那么我们必须保证先dfs2这个点,但如果按正常顺序dfs,我们会先枚举到1这个点,如果1在连了21之后与其他点连了边··直接dfs就会发生错误····

所以我们可以将1打个标记···在枚举到1的时候直接略过它··这样就可以保证会先dfs到2,再dfs到1···与1相连的其他点也会被dfs到····换句话说··如果连了一条边AB,我们要给B打一个标记····保证dfs时先dfs到点A,再dfs到点B

解决了dfs序的顺序后接下来就是线段树的基础操作了

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<cctype>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
const int N=3e5+;
const int inf=0x3f3f3f3f;
struct node
{
int x,y,op;
}q[N];
struct node1
{
int from,to;
}e[N];
int dfn[N],last[N],tree[N*],father[N],tag[N*],n,m,num[N],val[N],fst[N],go[N],nxt[N],tot,to,cnt,tol,pre[N];
bool jud[N];
inline void comb(int a,int b)
{
nxt[++tot]=fst[a],fst[a]=tot,go[tot]=b;
}
inline int getfa(int u)
{
if(father[u]==u) return u;
else return father[u]=getfa(father[u]);
}
inline int R()
{
char c;int f=,i=;
for(c=getchar();(c<''||c>'')&&c!='-';c=getchar());
if(c=='-') c=getchar(),i=-;
for(;c<=''&&c>='';c=getchar())
f=(f<<)+(f<<)+c-'';
return f*i;
}
inline void dfs(int u)
{
last[u]=dfn[u]=++cnt;
for(int e=fst[u];e;e=nxt[e]) dfs(go[e]);
}
inline void add(int k,int v)
{
tree[k]+=v;tag[k]+=v;
}
inline void pushdown(int k)
{
if(tag[k])
{
add(k*,tag[k]);
add(k*+,tag[k]);
tag[k]=;
}
}
inline void build(int k,int l,int r)
{
if(l==r)
{
tree[k]=val[l];return;
}
int mid=(l+r)/;
build(k*,l,mid);build(k*+,mid+,r);
tree[k]=max(tree[k*],tree[k*+]);
return;
}
inline void modify(int k,int l,int r,int x,int y,int v)
{
if(l>=x&&r<=y)
{
add(k,v);return;
}
int mid=(l+r)/;
pushdown(k);
if(x<=mid) modify(k*,l,mid,x,y,v);
if(y>mid) modify(k*+,mid+,r,x,y,v);
tree[k]=max(tree[k*],tree[k*+]);
}
inline int query(int k,int l,int r,int x,int y)
{
if(l>=x&&r<=y)
return tree[k];
int mid=(l+r)/;int temp=-inf;
pushdown(k);
if(x<=mid) temp=max(temp,query(k*,l,mid,x,y));
if(y>mid) temp=max(temp,query(k*+,mid+,r,x,y));
return temp;
}
int main()
{
//freopen("a.in","r",stdin);
//freopen("a.out","w",stdout);
memset(tree,-inf,sizeof(tree));
n=R();for(int i=;i<=n;i++) num[i]=R(),father[i]=i;
m=R();char s[];memset(jud,true,sizeof(jud));
for(int i=;i<=m;i++)
{
scanf("%s",s);
if(s[]=='U')
{
q[i].op=;q[i].x=R(),q[i].y=R();
int a=getfa(q[i].x),b=getfa(q[i].y);
if(a!=b) father[a]=b,jud[a]=false,e[++tol].from=b,e[tol].to=a;
}
else if(s[]=='A')
{
if(s[]=='') q[i].op=,q[i].x=R(),q[i].y=R();
if(s[]=='') q[i].op=,q[i].x=R(),q[i].y=R();
if(s[]=='') q[i].op=,q[i].x=R();
}
else if(s[]=='F')
{
if(s[]=='') q[i].op=,q[i].x=R();
if(s[]=='') q[i].op=,q[i].x=R();
if(s[]=='') q[i].op=;
}
}
for(int i=tol;i;i--) comb(e[i].from,e[i].to);
for(int i=;i<=n;i++)
{
father[i]=i;
if(!dfn[i]&&jud[i])
dfs(i);
}
for(int i=;i<=n;i++) pre[i]=dfn[i],val[dfn[i]]=num[i];build(,,n);
for(int i=;i<=m;i++)
{
if(q[i].op==)
{
int a=getfa(q[i].x),b=getfa(q[i].y);
if(a!=b) father[a]=b,dfn[b]=max(dfn[b],dfn[a]),last[b]=min(last[b],last[a]);
}
if(q[i].op==)
{
int a=q[i].x,b=q[i].y;
modify(,,n,pre[a],pre[a],b);
}
if(q[i].op==)
{
int a=getfa(q[i].x),b=q[i].y;
modify(,,n,last[a],dfn[a],b);
}
if(q[i].op==)
{
int a=q[i].x;
modify(,,n,,n,a);
}
if(q[i].op==)
{
int a=q[i].x;
printf("%d\n",query(,,n,pre[a],pre[a]));
}
if(q[i].op==)
{
int a=getfa(q[i].x);
printf("%d\n",query(,,n,last[a],dfn[a]));
}
if(q[i].op==)
printf("%d\n",query(,,n,,n));
}
return ;
}

刷题总结——棘手的操作(bzoj2333)的更多相关文章

  1. 【BZOJ2333】棘手的操作(左偏树,STL)

    [BZOJ2333]棘手的操作(左偏树,STL) 题面 BZOJ上看把... 题解 正如这题的题号 我只能\(2333\) 神TM棘手的题目... 前面的单点/联通块操作 很显然是一个左偏树+标记 ( ...

  2. 【bzoj2333】 SCOI2011—棘手的操作

    http://www.lydsy.com/JudgeOnline/problem.php?id=2333 (题目链接) 题意 N个节点维护一些操作.. Solution 我们用可并大根堆进行维护. 对 ...

  3. 真--可并堆模板--BZOJ2333: [SCOI2011]棘手的操作

    n<=300000个点,开始是独立的,m<=300000个操作: 方法一:单点修改.查询,区间修改.查询?等等等等这里修改是块修改不是连续的啊,那就让他连续呗!具体方法:离线后,每次连接两 ...

  4. 【bzoj2333】 [SCOI2011]棘手的操作 可并堆+lazy标记

    2016-05-31  21:45:41 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2333 (学习了黄学长的代码 有如下操作: U x y ...

  5. NOI题库分治算法刷题记录

    今天晚自习机房刷题,有一道题最终WA掉两组,极其不爽,晚上回家补完作业欣然搞定它,特意来写篇博文来记录下 (最想吐槽的是这个叫做分治的分类,里面的题目真的需要分治吗...) 先来说下分治法 分治法的设 ...

  6. 用js刷题的一些坑

    leecode可以用js刷题了,我大js越来越被认可了是吧.但是刷题中会因为忽略js的一些特性掉入坑里.我这里总结一下我掉过的坑. 坑1:js中数组对象是引用对象 js中除了object还有数组对象也 ...

  7. HDU 自动刷题机 Auto AC (轻轻松松进入HDU首页)

    前言: 在写这篇文章之前,首先感谢给我思路以及帮助过我的学长们 以下4篇博客都是学长原创,其中有很多有用的,值得学习的东西,希望能够帮到大家! 1.手把手教你用C++ 写ACM自动刷题神器(冲入HDU ...

  8. 【BZOJ 2333 】[SCOI2011]棘手的操作(离线+线段树)

    2333: [SCOI2011]棘手的操作 Description 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i],接下来有如下一些操作: U x y: 加一条边 ...

  9. python部落刷题宝学到的内置函数(二)

    感觉到刷题宝有一个好处,也许也不是好处,它的答案必须是真正输出的值,也就是说应该输出字符串aaaa的时候,答案必须写成界面上返回的值,即'aaaa'.有利于真正记忆返回值类型,但是....太繁琐了 1 ...

随机推荐

  1. UVA12904 Load Balancing(中途相遇法)

    虽然这题可以用暴力n^3过,但是还有有种n^2的方法的,枚举b,对于b,分别枚举a和c,得到对于这个b的最优解,然后从所以b中选一个最优的. 要保证字典序最小,只要从小往大枚举就好了 感谢moonfl ...

  2. [机器学习] 简单的机器学习算法和sklearn实现

    机器学习基础算法理解和总结 KNN算法 理解 KNN其实是最好理解的算法之一,其实就是依次和空间中的每个点进行距离比较,取距离最近的N个点,看这N个点的类别,那么要判断的点的类别就是这N个点中类别占比 ...

  3. FreeRTOS_信号量

    FreeRTOS信号量 信号量是操作系统总重要的一部分,信号量一般用来进行资源管理和任务同步,FreeRTOS中信号量又分为二值信号量.计数型信号量.互斥信号量和递归互斥信号量.不同的信号量其应用场景 ...

  4. 使用HelpProvide组件调用帮助文件

    实现效果: 知识运用: HelpProvider组件的HelpNameSpace属性 //于对象关联的帮助文件名 public virtual string HelpNameSpace {get; s ...

  5. CVE-2011-0065

      环境 备注 操作系统 Windows 7 x86 sp1 专业版 漏洞软件 Firefox 版本号:3.6.16 调试器 Windbg 版本号:6.12.0002.633 0x00 漏洞描述 在F ...

  6. 廖老师JavaScript教程高阶函数-sort用法

    先来学习一个新词:高阶函数 高阶函数英文叫Higher-order function.那么什么是高阶函数? JavaScript的函数其实都指向某个变量.既然变量可以指向函数,函数的参数能接收变量,那 ...

  7. Yum简单使用小结

      Yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器.基于RPM包管理,能够从指定的服务器自动 ...

  8. Check for Palindromes-freecodecamp算法题目

    Check for Palindromes(检查回文字符串) 要求 给定的字符串是回文,返回true,反之,返回false.(如果一个字符串忽略标点符号.大小写和空格,正着读和反着读一模一样,那么这个 ...

  9. 洛谷 4219/BZOJ 4530 大融合

    4530: [Bjoi2014]大融合 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 990  Solved: 604[Submit][Status] ...

  10. Scrapy+Chromium+代理+selenium

    上周说到scrapy的基本入门.这周来写写其中遇到的代理和js渲染的坑. js渲染 js是爬虫中毕竟麻烦处理的一块.通常的解决办法是通过抓包,然后查看request信息,接着捕获ajax返回的消息.但 ...