• bzoj2333 离线 + 线段树


    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=0;register char c=getchar();for(;!isdigit(c);c=getchar());
    for(;isdigit(c);now=now*10+c-'0',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
    ", x)
    #define Prl(x) printf("%lld
    ",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-9;
    const int maxn = 3e5 + 10;
    const int INF = 0x3f3f3f3f;
    const int mod = 1e9 + 7; 
    template <class T>
    inline bool scan_d(T &ret){
        char c; int sgn;
        if(c = getchar(),c == EOF) return 0;
        while(c != '-' && (c < '0' || c > '9')) c = getchar();
        sgn = (c == '-')?-1:1;
        ret = (c == '-')?0:(c - '0');
        while(c = getchar(),c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
        ret *= sgn;
        return 1;
    }
    int N,M,K;
    int a[maxn];
    struct Node{
        char op[3];
        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,1,N) ed[i] = fa[i] = i;
    }
    int pos[maxn],id[maxn];
    struct Tree{
        int l,r;
        int lazy,Max;
    }tree[maxn << 2];
    void Pushup(int t){
        tree[t].Max = max(tree[t << 1].Max,tree[t << 1 | 1].Max);
    }
    void Pushdown(int t){
        if(tree[t].lazy){
            tree[t << 1].lazy += tree[t].lazy; tree[t << 1 | 1].lazy += tree[t].lazy;
            tree[t << 1].Max += tree[t].lazy; tree[t << 1 | 1].Max += tree[t].lazy;
            tree[t].lazy = 0;
        }
    }
    void build(int t,int l,int r){
        tree[t].l = l; tree[t].r = r;
        tree[t].lazy = 0;
        if(l == r){
            tree[t].Max = a[id[l]];
            return ;
        }
        int m = (l + r) >> 1;
        build(t << 1,l,m); build(t << 1 | 1,m + 1,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) >> 1;
        if(r <= m) update(t << 1,l,r,v);
        else if(l > m) update(t << 1 | 1,l,r,v);
        else{
            update(t << 1,l,m,v); update(t << 1 | 1,m + 1,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) >> 1;
        if(r <= m) return query(t << 1,l,r);
        else if(l > m) return query(t << 1 | 1,l,r);
        return max(query(t << 1,l,m),query(t << 1 | 1,m + 1,r));
    }
    int main()
    {
        Sca(N);
        For(i,1,N) scan_d(a[i]);
        scan_d(M); init();
        for(int i = 0 ; i < M ; i ++ ){
            scanf("%s",node[i].op);
            if(node[i].op[0] == 'F'){
                if(node[i].op[1] == '3') continue;
                scan_d(node[i].x);
            }else if(node[i].op[0] == 'A' && node[i].op[1] == '3'){
                scan_d(node[i].x);
            }else{
                scan_d(node[i].x); scan_d(node[i].y);
            }
            if(node[i].op[0] == 'U') Union(node[i].x,node[i].y);
        }
        int cnt = 0;
        for(int i = 1; i <= N ; i ++){
            if(fa[i] != i) continue;
            for(int j = i; j;j = nxt[j]){
                pos[j] = ++cnt;
                id[cnt] = j;
            }
        }
        build(1,1,N); init();
        int sum = 0;
        for(int i = 0 ; i < M ; i ++){
            if(node[i].op[0] == 'U'){
                Union(node[i].x,node[i].y);
            }
            if(node[i].op[0] == 'A'){
                if(node[i].op[1] == '1'){
                    node[i].x = pos[node[i].x];
                    update(1,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[1] == '2'){
                    int t = find(node[i].x);
                    update(1,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[0] == 'F'){
                if(node[i].op[1] == '1'){
                    Pri(query(1,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[1] == '2'){
                    int t = find(node[i].x);
                   // cout << "query" << pos[t] << "  " << pos[ed[t]] << endl;
                    Pri(query(1,pos[t],pos[ed[t]]) + sum);
                }else{
                    Pri(tree[1].Max + sum);
                }
            }
        }
        #ifdef VSCode
        system("pause");
        #endif
        return 0;
    }

     

     

  • 相关阅读:
    jQuery遍历
    jQuery DOM
    jQuery表单事件
    jQuery事件对象
    jQuery绑定事物处理器
    jQuery事件
    JQuery基础选择器
    JQuery基础 接下来我将把我最近学习jQuery所做的笔记发布,希望对初学者有些许帮助,也方便自己以后复习
    C# 连接Oracle数据库 遇到“System.Data.OracleClient 需要 Oracle 客户端软件 8.1.7 或更高版本”的解决方案
    安装oracle11版本报错此先决条件将测试系统物理内存总量是否至少为 922MB
  • 原文地址:https://www.cnblogs.com/Hugh-Locke/p/9830445.html
Copyright © 2020-2023  润新知