2333: [SCOI2011]棘手的操作

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 1979  Solved: 772
[Submit][Status][Discuss]

Description

有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: 输出所有节点中,权值最大的节点的权值

Input

输入的第一行是一个整数N,代表节点个数。

接下来一行输入N个整数,a[1], a[2], …, a[N],代表N个节点的初始权值。

再下一行输入一个整数Q,代表接下来的操作数。

最后输入Q行,每行的格式如题目描述所示。

Output

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

Sample Input

3

0 0 0

8

A1 3 -20

A1 2 20

U 1 3

A2 1 10

F1 3

F2 3

A3 -10

F3

Sample Output

-10

10

10

HINT

对于30%的数据,保证 N<=100,Q<=10000

对于80%的数据,保证 N<=100000,Q<=100000

对于100%的数据,保证 N<=300000,Q<=300000

对于所有的数据,保证输入合法,并且 -1000<=v, a[1], a[2], …, a[N]<=1000

Source


可并堆真是个玄学的东西我不玩了!!!
复杂度怎么分析怎么不对啊,怎么可以像平衡树那样打标记呢?
并且怎么写怎么不对........
最后无奈照黄学长抄了个代码,内层左偏树或者斜堆都可以,外层set必须用s.erase(s.find(v))
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
#define lc t[x].l
#define rc t[x].r
typedef long long ll;
const int N=3e5+,INF=1e9;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-; c=getchar();}
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return x*f;
}
int n,Q,x,y,v;
char s[]; struct node{
int l,r,fa,v,add;
}t[N];
inline int find(int x){
while(t[x].fa) x=t[x].fa;
return x;
}
inline void pushDown(int x){
if(t[x].add){
if(lc) t[lc].v+=t[x].add,t[lc].add+=t[x].add;
if(rc) t[rc].v+=t[x].add,t[rc].add+=t[x].add;
t[x].add=;
}
}
int st[N];
inline void PD(int x){
while(x) st[++st[]]=x,x=t[x].fa;
while(st[]) pushDown(st[st[]--]);
}
inline int Top(int x){
return t[find(x)].v;
}
int Merge(int x,int y){
if(x==||y==) return x+y;
if(t[x].v<t[y].v) swap(x,y);
pushDown(x);
rc=Merge(rc,y);
t[rc].fa=x;
swap(lc,rc);
return x;
}
int Del(int x){
pushDown(x);//no
int f=t[x].fa,y=Merge(lc,rc);
t[y].fa=f;
if(t[f].l==x) t[f].l=y;
else t[f].r=y;
t[x].l=t[x].r=t[x].fa=;
return find(y);
}
multiset<int> S;
inline void erase(int v){
S.erase(S.find(v));
}
inline void U(int x,int y){
x=find(x);y=find(y);
if(x!=y){
if(Merge(x,y)==x) erase(t[y].v);
else erase(t[x].v);
}
}
inline void A1(int x,int v){
PD(x);
erase(t[find(x)].v);
t[x].v+=v;
S.insert(t[Merge(Del(x),x)].v);
}
inline void A2(int x,int v){
int f=find(x);
erase(t[f].v);
t[f].add+=v;t[f].v+=v;
S.insert(t[f].v);
}
int ADD;
inline void F1(int x){
PD(x);
printf("%d\n",t[x].v+ADD);
}
int main(){
//freopen("in.txt","r",stdin);
n=read();
for(int i=;i<=n;i++){
t[i].v=read();
S.insert(t[i].v);
}
Q=read();
while(Q--){
scanf("%s",s);
if(s[]=='U') x=read(),y=read(),U(x,y);
if(s[]=='A'){
x=read();
if(s[]=='') v=read(),A1(x,v);
if(s[]=='') v=read(),A2(x,v);
if(s[]=='') ADD+=x;
}
if(s[]=='F'){
if(s[]=='') x=read(),F1(x);
if(s[]=='') x=read(),printf("%d\n",t[find(x)].v+ADD);
if(s[]=='') printf("%d\n",*--S.end()+ADD);
}
}
}

下面是当时写了一个下午的WA代码

 
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define lc t[x].l
#define rc t[x].r
typedef long long ll;
const int N=3e5+,INF=1e9;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-; c=getchar();}
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return x*f;
}
int n,Q,x,y,v;
char s[]; int fa[N];
inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
struct node{
int l,r,fa,v,d,size;
}t[N];
int add[N];
//inline void update(int x){t[x].size=t[lc].size+t[rc].size+1;}
void Add(int x,int v){
t[x].v+=v;
if(lc) Add(lc,v);
if(rc) Add(rc,v);
}
int Merge(int x,int y){//printf("Merge %d %d\n",x,y);
if(x==||y==) return x+y;
if(t[x].v<t[y].v) swap(x,y);
rc=Merge(rc,y);
// update(x);printf("MS %d %d\n",x,t[x].size);
t[rc].fa=x;
if(t[lc].d<t[rc].d) swap(lc,rc);
t[x].d=t[rc].d+;
return x;
}
int Del(int x){
int f=t[x].fa,y=Merge(lc,rc);
t[y].fa=f;
if(f&&t[f].l==x) t[f].l=y;
if(f&&t[f].r==x) t[f].r=y;
// update(f);
int re=f?find(f):y;
t[x].l=t[x].r=t[x].fa=t[x].d=;
x=f;
while(x){
if(t[lc].d<t[rc].d) swap(lc,rc);
if(t[rc].d+==t[x].d) break;
t[x].d=t[rc].d+;
x=t[x].fa;
}
return re;
} namespace S{ struct node{
int l,r,fa,v,d;
}t[N];
int root;
int Merge(int x,int y){//printf("Merge %d %d\n",x,y);
if(x==||y==) return x+y;
if(t[x].v<t[y].v) swap(x,y);
rc=Merge(rc,y);
t[rc].fa=x;
if(t[lc].d<t[rc].d) swap(lc,rc);
t[x].d=t[rc].d+;
return x;
}
int Del(int x){
int f=t[x].fa,y=Merge(lc,rc);
t[y].fa=f;
if(f&&t[f].l==x) t[f].l=y;
if(f&&t[f].r==x) t[f].r=y;
int re=f?find(f):y;
t[x].l=t[x].r=t[x].fa=t[x].d=;
x=f;
while(x){
if(t[lc].d<t[rc].d) swap(lc,rc);
if(t[rc].d+==t[x].d) break;
t[x].d=t[rc].d+;
x=t[x].fa;
}//printf("DElre %d\n",re);
return re;
} int q[N],head,tail;
inline void lop(int &x){if(x==N) x=;}
void Heapify(){
head=tail=;
for(int i=;i<=n;i++) q[tail++]=i;
int x,y,z;
while(head!=tail){
x=q[head++];lop(head);
if(head!=tail) y=q[head++],lop(head);
else break;
z=Merge(x,y);
q[tail++]=z;lop(tail);
}
root=x;
} } inline void U(int x,int y){
x=find(x);y=find(y);
if(x!=y){
S::Del(x);
S::Del(y);//printf("IWantToSeeSize %d %d\n",t[x].size,t[y].size);
if(t[x].size>t[y].size) swap(x,y);
Add(x,add[x]-add[y]);
int z=fa[x]=fa[y]=Merge(x,y);//printf("M %d %d %d %d %d %d\n",x,y,z,t[x].v,t[y].v,t[z].v);
add[z]=add[y];//printf("hiz %d %d %d %d\n",z,S::t[z].v,S::root,S::t[S::root].v);
t[z].size=t[x].size+t[y].size;
S::root=S::Merge(S::root,z);//printf("hiroot %d %d\n",S::root,S::t[S::root].v);
}
}
inline void A1(int x,int v){
int fx=find(x);
S::root=S::Del(fx); int _add=add[fx],_size=t[fx].size;
int y=Del(x);
t[x].v+=v;//printf("what %d %d\n",x,y);
int z=fa[x]=fa[y]=Merge(x,y);
//printf("A1 %d %d %d\nAS %d %d %d\n",x,y,z,t[x].size,t[y].size,t[z].size);
add[z]=_add;t[z].size=_size; S::t[z].v=t[z].v+add[z];
S::root=Merge(S::root,z);
}
inline void A2(int x,int v){
x=find(x);
S::root=S::Del(x);
add[x]+=v;
S::t[x].v=t[x].v+add[x];
S::root=Merge(S::root,x);
}
int ADD;
inline void A3(int v){ADD+=v;}
inline void F1(int x){
int fx=find(x);
printf("%d\n",t[x].v+add[fx]+ADD);
}
inline void F2(int x){
int fx=find(x);
printf("%d\n",t[fx].v+add[fx]+ADD);
}
inline void F3(){printf("%d\n",S::t[S::root].v+ADD);}
int main(){
//freopen("in.txt","r",stdin);
n=read();
for(int i=;i<=n;i++){
t[i].v=S::t[i].v=read();
t[i].size=; fa[i]=i;
}
t[].d=S::t[].d=-;
S::Heapify();
Q=read();//printf("BEGIN\n");
while(Q--){ //printf("QQQQQQQQQ %d\n",Q);
scanf("%s",s);
if(s[]=='U') x=read(),y=read(),U(x,y);
if(s[]=='A'){
x=read();
if(s[]=='') v=read(),A1(x,v);
if(s[]=='') v=read(),A2(x,v);
if(s[]=='') A3(x);
}
if(s[]=='F'){
if(s[]=='') x=read(),F1(x);
if(s[]=='') x=read(),F2(x);
if(s[]=='') F3();
}
}
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
#define lc t[x].l
#define rc t[x].r
typedef long long ll;
const int N=3e5+,INF=1e9;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-; c=getchar();}
while(c>=''&&c<=''){x=x*+c-''; c=getchar();}
return x*f;
}
int n,Q,x,y,v;
char s[]; struct node{
int l,r,fa,v,d,add;
}t[N];
inline int find(int x){
while(t[x].fa) x=t[x].fa;
return x;
}
inline void pushDown(int x){
if(t[x].add){
if(lc) t[lc].v+=t[x].add;
if(rc) t[rc].v+=t[x].add;
t[x].add=;
}
}
int st[N],top;
inline void PD(int x){
while(x) st[++top]=x,x=t[x].fa;
while(top) pushDown(st[top--]);
} int Merge(int x,int y){
if(x==||y==) return x+y;
if(t[x].v<t[y].v) swap(x,y);
pushDown(x);
rc=Merge(rc,y);
t[rc].fa=x;
if(t[lc].d<t[rc].d) swap(lc,rc);
t[x].d=t[rc].d+;
return x;
}
int Del(int x){
pushDown(x);
int f=t[x].fa,y=Merge(lc,rc);
t[y].fa=f;
if(f&&t[f].l==x) t[f].l=y;
if(f&&t[f].r==x) t[f].r=y;
t[x].l=t[x].r=t[x].fa=t[x].d=;
x=f;
while(x){
if(t[lc].d<t[rc].d) swap(lc,rc);
if(t[rc].d+==t[x].d) break;
t[x].d=t[rc].d+;
x=t[x].fa;
}
return find(y);
}
multiset<int> S;
inline void U(int x,int y){
x=find(x);y=find(y);
if(x!=y){
if(Merge(x,y)==x) S.erase(t[y].v);
else S.erase(t[x].v);
}
}
inline void A1(int x,int v){
PD(x);
S.erase(t[find(x)].v);
t[x].v+=v;
S.insert(t[Merge(Del(x),x)].v);
}
inline void A2(int x,int v){
int f=find(x);
S.erase(t[f].v);
t[f].add+=v;t[f].v+=v;
S.insert(t[f].v);
}
int ADD;
inline void F1(int x){
PD(x);
printf("%d\n",t[x].v+ADD);
}
int main(){
//freopen("in.txt","r",stdin);
n=read();
for(int i=;i<=n;i++){
t[i].v=read();
S.insert(t[i].v);
}
t[].d=-;
Q=read();
while(Q--){
scanf("%s",s);
if(s[]=='U') x=read(),y=read(),U(x,y);
if(s[]=='A'){
x=read();
if(s[]=='') v=read(),A1(x,v);
if(s[]=='') v=read(),A2(x,v);
if(s[]=='') ADD+=x;
}
if(s[]=='F'){
if(s[]=='') x=read(),F1(x);
if(s[]=='') x=read(),printf("%d\n",t[find(x)].v+ADD);
if(s[]=='') printf("%d\n",*--S.end()+ADD);
}
}
}

2333: [SCOI2011]棘手的操作[我不玩了]的更多相关文章

  1. 2333: [SCOI2011]棘手的操作[写不出来]

    2333: [SCOI2011]棘手的操作 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1979  Solved: 772[Submit][Stat ...

  2. 2333: [SCOI2011]棘手的操作[离线线段树]

    2333: [SCOI2011]棘手的操作 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2325  Solved: 909[Submit][Stat ...

  3. BZOJ 2333: [SCOI2011]棘手的操作

    题目描述 真的是个很棘手的操作.. 注意每删除一个点,就需要clear一次. #include<complex> #include<cstdio> using namespac ...

  4. BZOJ 2333 SCOI2011 棘手的操作 并查集+可并堆

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2333 ..题意概述就不写了,各位老爷如果是看着玩的可以去搜一下,如果是做题找来的也知道题干 ...

  5. 【BZOJ】2333: [SCOI2011]棘手的操作

    http://www.lydsy.com/JudgeOnline/problem.php?id=2333 题意: 有N个节点,标号从1到N,这N个节点一开始相互不连通.第i个节点的初始权值为a[i], ...

  6. BZOJ 2333: [SCOI2011]棘手的操作 可并堆 左偏树 set

    https://www.lydsy.com/JudgeOnline/problem.php?id=2333 需要两个结构分别维护每个连通块的最大值和所有连通块最大值中的最大值,可以用两个可并堆实现,也 ...

  7. bzoj 2333 [SCOI2011]棘手的操作 —— 可并堆

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2333 稍微复杂,参考了博客:http://hzwer.com/5780.html 用 set ...

  8. BZOJ 2333 [SCOI2011]棘手的操作 (可并堆)

    码农题.. 很显然除了两个全局操作都能用可并堆完成 全局最大值用个multiset记录,每次合并时搞一搞就行了 注意使用multiset删除元素时 如果直接delete一个值,会把和这个值相同的所有元 ...

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

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

随机推荐

  1. MongoDB警告信息

    更多内容推荐微信公众号,欢迎关注: MongoDB警告信息: 1. WARNING: Using the XFS filesystem is strongly recommended with the ...

  2. Once you eliminate all the other factors,the only thing remaining must be the truth.

    Once you eliminate all the other factors,the only thing remaining must be the truth. 一旦你排除了杂因,剩下的一定是 ...

  3. MFC将二进制文件导入资源后释放

    1.前言 前一篇笔记记录了怎么修改PE,此篇记录下如何利用自身的资源文件. 2.编程思路 获得资源句柄 - 获得资源文件大小 - 加载资源文件 - 锁定资源并获得其指针. 3.实践代码 1)编译以下代 ...

  4. [MySQL FAQ]系列 — EXPLAIN结果中哪些信息要引起关注

    我们使用EXPLAIN解析SQL执行计划时,如果有下面几种情况,就需要特别关注下了: 首先看下 type 这列的结果,如果有类型是 ALL 时,表示预计会进行全表扫描(full table scan) ...

  5. linux kernel的中断子系统之(三):IRQ number和中断描述符【转】

    转自:http://www.wowotech.net/linux_kenrel/interrupt_descriptor.html 一.前言 本文主要围绕IRQ number和中断描述符(interr ...

  6. ETL利器Kettle实战应用解析系列二

    本系列文章主要索引如下: 一.ETL利器Kettle实战应用解析系列一[Kettle使用介绍] 二.ETL利器Kettle实战应用解析系列二 [应用场景和实战DEMO下载] 三.ETL利器Kettle ...

  7. static, const 和 static const 变量的初始化问题

    const 常量的在超出其作用域的时候会被释放,但是 static 静态变量在其作用域之外并没有释放,只是不能访问. static 修饰的是静态变量,静态函数.对于类来说,静态成员和静态函数是属于整个 ...

  8. jQuery-对标签的样式操作

    一.操作样式类 // 1.给标签添加样式类 $("选择器").addClass("类名") // 2.移除标签的样式类 $("选择器").r ...

  9. TF-池化函数 tf.nn.max_pool 的介绍

    转载自此大神 http://blog.csdn.net/mao_xiao_feng/article/details/53453926 max pooling是CNN当中的最大值池化操作,其实用法和卷积 ...

  10. Python 正则表达式提高

    re模块的高级用法 search re.search(pattern, string[, flags]) ​ 若string中包含pattern子串,则返回Match对象,否则返回None,注意,如果 ...