zoukankan      html  css  js  c++  java
  • [Codeforces Round #254 div1] C.DZY Loves Colors 【线段树】

    题目链接:CF Round #254 div1 C

    题目分析

    这道题目是要实现区间赋值的操作,同时还要根据区间中原先的值修改区间上的属性权值。

    如果直接使用普通的线段树区间赋值的方法,当一个节点表示的区间完全被要求修改的区间包含时,就直接打上赋值的标记然后 return 。但是这样这个节点中每个位置原先的值不同,需要进行的属性权值修改也就不同,是不能直接实现的。如果我们在节点表示的区间被修改的区间包含时,并不直接打标记 return ,而是当节点表示的区间被修改的区间完全包含而且这个节点中的每个位置的颜色相同时,才直接打标记然后 return ,否则就继续递归下去。这样就可以直接打标记修改属性权值了。但是这样看起来是会使复杂度退化的,但是实际上通过一些我不懂的势能分析,这样修改复杂度还是 O(log n) 的。所以这样这道题就变成线段树水题了。

    需要维护一下每个节点表示的区间是否颜色相同。

    区间赋值的题目就可以使用这种修改方式。

    代码

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long LL;
    
    inline int Abs(int x) {return x < 0 ? -x : x;}
    
    const int MaxN = 100000 + 5;
    
    int n, m;
    int Col[MaxN * 4], Len[MaxN * 4], Pc[MaxN * 4];
    
    LL T[MaxN * 4], D[MaxN * 4];
    
    bool Same[MaxN * 4];
    
    inline void Update(int x)
    {
    	Same[x] = Same[x << 1] && Same[x << 1 | 1] && Col[x << 1] == Col[x << 1 | 1];
    	if (Same[x]) Col[x] = Col[x << 1]; 
    	T[x] = T[x << 1] + T[x << 1 | 1];
    	Len[x] = Len[x << 1] + Len[x << 1 | 1];
    }
    
    inline void Add(int x, LL Num)
    {
    	D[x] += Num;
    	T[x] += (LL)Len[x] * Num;
    }
    
    inline void PushDown(int x)
    {
    	if (D[x] != 0)
    	{
    		Add(x << 1, D[x]);
    		Add(x << 1 | 1, D[x]);
    		D[x] = 0;
    	}
    	if (Pc[x] != 0)
    	{
    		Col[x << 1] = Pc[x << 1] = Pc[x];
    		Col[x << 1 | 1] = Pc[x << 1 | 1] = Pc[x];
    		Pc[x] = 0;
    	}
    }
    
    void Build(int x, int s, int t)	
    {	
    	if (s == t)
    	{
    		Same[x] = true;
    		Col[x] = s;
    		T[x] = D[x] = Pc[x] = 0;
    		Len[x] = 1;
    		return;
    	}
    	int m = (s + t) >> 1;
    	Build(x << 1, s, m);
    	Build(x << 1 | 1, m + 1, t);
    	Update(x); 
    }
    
    void Change(int x, int s, int t, int l, int r, int Num)
    {
    	if (l <= s && r >= t && Same[x])
    	{
    		int Temp = Abs(Col[x] - Num);
    		D[x] += (LL)Temp;
    		T[x] += (LL)Temp * (LL)Len[x];
    		Col[x] = Pc[x] = Num;		
    		return;
    	}
    	PushDown(x);
    	int m = (s + t) >> 1;
    	if (l <= m) Change(x << 1, s, m, l, r, Num);
    	if (r >= m + 1) Change(x << 1 | 1, m + 1, t, l, r, Num);
    	Update(x);
    }
    
    LL Query(int x, int s, int t, int l, int r)
    {
    	if (l <= s && r >= t) return T[x];
    	PushDown(x);
    	int m = (s + t) >> 1;
    	LL ret = 0;
    	if (l <= m) ret += Query(x << 1, s, m, l, r);
    	if (r >= m + 1) ret += Query(x << 1 | 1, m + 1, t, l, r);
    	return ret; 
    }
    
    int main()
    {
    	scanf("%d%d", &n, &m);	
    	Build(1, 1, n);	
    	int f, l, r, Num;
    	for (int i = 1; i <= m; ++i)
    	{
    		scanf("%d%d%d", &f, &l, &r);
    		if (f == 1) 
    		{
    			scanf("%d", &Num);
    			Change(1, 1, n, l, r, Num);
    		}
    		else printf("%I64d
    ", Query(1, 1, n, l, r));
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    基于SpringBoot+Mybatis+AntDesign快速开发平台,Jeecg-Boot 1.1 版本发布
    jeecg-boot 简易部署方案
    JeecgBoot版本4月份新版即将发布,抢先体验。。
    Jeecg-Boot 1.0版本发布,企业级快速开发平台
    jeecg之弹窗插件lhgdialog小结
    JEECG 集成KiSSO单点登录实现统一身份认证
    sass
    http1.1管线话 vs htttp2.0 多路复用
    http 状态码
    http参考
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4531606.html
Copyright © 2011-2022 走看看