zoukankan      html  css  js  c++  java
  • 洛谷T44252 线索_分治线段树_思维题

    分治线段树,其实就是将标记永久化,到最后再统一下传所有标记。
    至于先后顺序,可以给每个节点开一个时间戳。
    一般地,分治线段树用于离线,只查询一次答案的题目。
    本题中,标记要被下传 22 次。
    Code:

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxn = 100000 + 10;
    int n,m,  tag[maxn << 2], lazy[maxn << 2], siz[maxn], root[maxn], p[maxn], tag_root[maxn], ans[maxn];
    int find(int x){ return p[x] == x ? x : p[x] = find(p[x]);  }
    struct Segment_Tree
    {
        # define lson (o << 1)
        # define rson (o << 1)|1 
        void update(int l, int r, int L, int R, int col, int times, int o)    
        {
            if(l > r || r < L || l > R) return ;
            if(l >= L && r <= R)
            {
                lazy[o] = col, tag[o] = times;
                return;
            }
            int mid = (l + r) >> 1;
            update(l, mid, L, R,col, times, lson);
            update(mid + 1, r, L, R, col , times, rson);
        }
        inline void pushdown(int o)
        {
            if(tag[o] > tag[lson]) 
                lazy[lson] = lazy[o], tag[lson] = tag[o];   
            if(tag[o] > tag[rson]) 
                lazy[rson] = lazy[o], tag[rson] = tag[o];
        }
        void release(int o, int l, int r)
        {
            if(l > r) return ;
            if(l == r)
            {
                int x = find(l);
                if(tag_root[x] > tag[o])
                    ans[l] = root[x];
                else 
                    ans[l] = lazy[o], tag_root[x] = tag[o], root[x] = lazy[o];
                return ;
            }
            int mid = (l + r) >> 1;
            pushdown(o);
            release(lson, l, mid);
            release(rson, mid + 1, r);
        }
    }T;
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i = 1;i <= n; ++i) 
        { 
            int c; scanf("%d",&c);
            p[i] = i, root[i] = c, siz[i] = 1, tag_root[i] = 1;
        }  
        for(int i = 2;i <= m + 1; ++i)
        {  
            int opt, l, r, x; 
            scanf("%d%d%d%d",&opt,&l,&r,&x); 
            switch(opt) 
            {
                case 1:
                    T.update(1, n, l, r, x, i, 1);
                    break;
                case 2:
                    int a = find(l), b = find(r);
                    root[b] = x, tag_root[b] = i;
                    if(a != b) { p[a] = b, siz[b] += siz[a]; }
                    break;
            }
        }
        T.release(1, 1, n);
        T.release(1, 1, n);
        for(int i = 1;i <= n; ++i) printf("%d ",ans[i]);
        printf("
    ");
        for(int i = 1;i <= n; ++i)
        {
            int x = find(i);
            printf("%d ",siz[x] - 1);
        }
        return 0;
    }
    
  • 相关阅读:
    VB程序破解常用函数
    去VB程序NAG窗口方法-4C法
    error LNK2005: _DllMain@12 已经在 XXXX.obj 中定义
    汇编中的test和cmp指令
    OD保存修改后的数据到EXE
    C++ 异常捕获 try 和 __try的区别
    CListCtrl选中行
    WindowsAPI解析IAT地址
    Usaco 4.3.1 Buy Low, Buy Lower 逢低吸纳详细解题报告
    全国青少年信息学奥林匹克分区联赛(N)竞赛大纲
  • 原文地址:https://www.cnblogs.com/guangheli/p/9845113.html
Copyright © 2011-2022 走看看