https://www.lydsy.com/JudgeOnline/problem.php?id=2333

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

题意

看起来像一道可并堆的硬核数据结构题。

实际上确实是一道可并堆的数据结构题。

但我不会

那我有什么办法,只能用离线 + 线段树做了。

离线处理交换位置,保证所有连边的点都相邻,然后直接上区间修改+区间查询。

思路不难,就是写起来有点烦

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
inline int read(){int now=;register char c=getchar();for(;!isdigit(c);c=getchar());
for(;isdigit(c);now=now*+c-'',c=getchar());return now;}
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
const double eps = 1e-;
const int maxn = 3e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
template <class T>
inline bool scan_d(T &ret){
char c; int sgn;
if(c = getchar(),c == EOF) return ;
while(c != '-' && (c < '' || c > '')) c = getchar();
sgn = (c == '-')?-:;
ret = (c == '-')?:(c - '');
while(c = getchar(),c >= '' && c <= '') ret = ret * + (c - '');
ret *= sgn;
return ;
}
int N,M,K;
int a[maxn];
struct Node{
char op[];
int x,y;
}node[maxn];
int nxt[maxn],ed[maxn];
int fa[maxn];
int find(int p){
if(p == fa[p]) return p;
return fa[p] = find(fa[p]);
}
void Union(int a,int b){
a = find(a); b = find(b);
if(a == b) return;
nxt[ed[a]] = b;
ed[a] = ed[b];
fa[b] = a;
}
void init(){
For(i,,N) ed[i] = fa[i] = i;
}
int pos[maxn],id[maxn];
struct Tree{
int l,r;
int lazy,Max;
}tree[maxn << ];
void Pushup(int t){
tree[t].Max = max(tree[t << ].Max,tree[t << | ].Max);
}
void Pushdown(int t){
if(tree[t].lazy){
tree[t << ].lazy += tree[t].lazy; tree[t << | ].lazy += tree[t].lazy;
tree[t << ].Max += tree[t].lazy; tree[t << | ].Max += tree[t].lazy;
tree[t].lazy = ;
}
}
void build(int t,int l,int r){
tree[t].l = l; tree[t].r = r;
tree[t].lazy = ;
if(l == r){
tree[t].Max = a[id[l]];
return ;
}
int m = (l + r) >> ;
build(t << ,l,m); build(t << | ,m + ,r);
Pushup(t);
}
void update(int t,int l,int r,int v){
if(l <= tree[t].l && tree[t].r <= r){
tree[t].Max += v;
tree[t].lazy += v;
return ;
}
Pushdown(t);
int m = (tree[t].l + tree[t].r) >> ;
if(r <= m) update(t << ,l,r,v);
else if(l > m) update(t << | ,l,r,v);
else{
update(t << ,l,m,v); update(t << | ,m + ,r,v);
}
Pushup(t);
}
int query(int t,int l,int r){
if(l <= tree[t].l && tree[t].r <= r){
return tree[t].Max;
}
Pushdown(t);
int m = (tree[t].l + tree[t].r) >> ;
if(r <= m) return query(t << ,l,r);
else if(l > m) return query(t << | ,l,r);
return max(query(t << ,l,m),query(t << | ,m + ,r));
}
int main()
{
Sca(N);
For(i,,N) scan_d(a[i]);
scan_d(M); init();
for(int i = ; i < M ; i ++ ){
scanf("%s",node[i].op);
if(node[i].op[] == 'F'){
if(node[i].op[] == '') continue;
scan_d(node[i].x);
}else if(node[i].op[] == 'A' && node[i].op[] == ''){
scan_d(node[i].x);
}else{
scan_d(node[i].x); scan_d(node[i].y);
}
if(node[i].op[] == 'U') Union(node[i].x,node[i].y);
}
int cnt = ;
for(int i = ; i <= N ; i ++){
if(fa[i] != i) continue;
for(int j = i; j;j = nxt[j]){
pos[j] = ++cnt;
id[cnt] = j;
}
}
build(,,N); init();
int sum = ;
for(int i = ; i < M ; i ++){
if(node[i].op[] == 'U'){
Union(node[i].x,node[i].y);
}
if(node[i].op[] == 'A'){
if(node[i].op[] == ''){
node[i].x = pos[node[i].x];
update(,node[i].x,node[i].x,node[i].y);
// cout << "update" << node[i].x << " " << node[i].x << " " << node[i].y << endl;
}else if(node[i].op[] == ''){
int t = find(node[i].x);
update(,pos[t],pos[ed[t]],node[i].y);
// cout << "update" << pos[t] << " " << pos[ed[t]] << " " << node[i].y << endl;
}else{
sum += node[i].x;
}
}else if(node[i].op[] == 'F'){
if(node[i].op[] == ''){
Pri(query(,pos[node[i].x],pos[node[i].x]) + sum);
// cout << "query" << pos[node[i].x] << " " << pos[node[i].x] << endl;
}else if(node[i].op[] == ''){
int t = find(node[i].x);
// cout << "query" << pos[t] << " " << pos[ed[t]] << endl;
Pri(query(,pos[t],pos[ed[t]]) + sum);
}else{
Pri(tree[].Max + sum);
}
}
}
#ifdef VSCode
system("pause");
#endif
return ;
}

bzoj2333 离线 + 线段树的更多相关文章

  1. hdu 4288 离线线段树+间隔求和

    Coder Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Su ...

  2. HDU 5700 区间交 离线线段树

    区间交 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5700 Description 小A有一个含有n个非负整数的数列与m个区间.每个区间可以表示为 ...

  3. BZOJ 3626 [LNOI2014]LCA 树剖+(离线+线段树 // 在线+主席树)

    BZOJ 4012 [HNOI2015]开店 的弱化版,离线了,而且没有边权(长度). 两种做法 1 树剖+离线+线段树 这道题求的是一个点zzz与[l,r][l,r][l,r]内所有点的lcalca ...

  4. BZOJ2333 [SCOI2011]棘手的操作 【离线 + 线段树】

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

  5. 【BZOJ 3443】 3443: 装备合成 (离线+线段树)

    3443: 装备合成 Time Limit: 15 Sec  Memory Limit: 128 MBSubmit: 63  Solved: 31 Description [背景]     lll69 ...

  6. HDU 4031 Attack(离线+线段树)(The 36th ACM/ICPC Asia Regional Chengdu Site —— Online Contest)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4031 Problem Description Today is the 10th Annual of ...

  7. Codeforces Round #365 (Div. 2) D. Mishka and Interesting sum 离线+线段树

    题目链接: http://codeforces.com/contest/703/problem/D D. Mishka and Interesting sum time limit per test ...

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

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

  9. HDU 4605 Magic Ball Game (在线主席树|| 离线 线段树)

    转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents    by---cxlove 题意:给出一棵二叉树,每个结点孩子数目为0或者2. ...

随机推荐

  1. 微信小程序——代码片段汇集

    导航栏 作者:beatzcs       链接:https://www.jianshu.com/p/c681007a6287 这个导航虽然已经很完善了,不过还是要根据自己的来进行修改的 tabs.wx ...

  2. Educational Codeforces Round 61 (Rated for Div. 2)

    A. Regular Bracket Sequence 题意:给出四种括号的数量 ((  )) ()  )( 问是否可以组成合法的序列(只能排序不能插在另外一个的中间) 思路: 条件一:一个或 n个) ...

  3. Codeforces1063D Candies for Children 【分类讨论】【暴力】

    题目分析: 首先要想两个暴力,一个的时间复杂度是$O(n^2)$,另一个是$O([\frac{n}{k}])$的. $n^2$的暴力可以枚举两段,一段有$i$个取两个的小朋友,一段有$j$个取两个的小 ...

  4. 洛谷P2670扫雷游戏题解

    题目 这道题是一个简单的模拟搜索题,可以把每个雷的位置都记作1. 这样就可记录出数字啦 #include<iostream> #include<cstring> using n ...

  5. 云服务器搭建在线ssh终端GateOne

    由于公司在使用内网和安全桌面,不能在安全桌面中安装Xshell的ssh终端,所有想操作个人公网服务器很困难. 查阅发现,使用GateOne可以在服务器上搭建一个在线的ssh工具.使用体验友好,可以满足 ...

  6. ubuntu 16.04 主题美化及终端美化

    如果你使用的是图形界面,你会发现ubuntu默认的界面真是丑的一批,所以简单美化一下: 1.安装unity-tweak-tool: sudo apt-get install unity-tweak-t ...

  7. Markdown 使用技巧

    懒得复制,直接贴网页吧 懒得复制,直接贴网页吧*2 懒得复制,直接贴网页吧*3

  8. CS Academy Gcd on a Circle(dp + 线段树)

    题意 给你一个长为 \(n\) 的环,你可以把它断成任意 \(k\) 段 \((1 < k \le n)\) ,使得每一段的 \(\gcd\) 都 \(>1\) . 问总共有多少种方案,对 ...

  9. 【BZOJ4868】[六省联考2017]期末考试(贪心)

    [BZOJ4868][六省联考2017]期末考试(贪心) 题面 BZOJ 洛谷 题解 显然最终的答案之和最后一个公布成绩的课程相关. 枚举最后一天的日期,那么维护一下前面有多少天可以向后移,后面总共需 ...

  10. cf406E Hamming Triples (推公式)

    考虑某两行a和b的dis 如果相同:$|a-b|$ 如果不同:$n-|a-b|$ 然后考虑三行的dis,不妨设a>=b>=c 那么有4种情况: 1.a,b,c 0/1的种类相同:$|a-b ...