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;
    }
    
  • 相关阅读:
    LINQ体验(6)——LINQ语句之Join和Order By
    转 Spring.NET 与 NHibernate 的整合
    项目经理人必须要遵循的14个成功原则
    做成功的项目经理人
    就业模拟试题_Net(答案)
    java中的23中设计模式
    七种武器——.NET工程师求职面试必杀技
    如何识别真正的程序员
    WCF传输大数据的设置
    就业模拟试题_Java(答案)
  • 原文地址:https://www.cnblogs.com/guangheli/p/9845113.html
Copyright © 2011-2022 走看看