Codeforces 444C(线段树)

区间颜色不一致就更新到底,否则lazy标记

#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
#define lc l,m,index<<1
#define rc m+1,r,index<<1|1
#define N 100005
#define ll __int64

struct node
{
	bool same;
	ll col,sum,add;
}seg[N<<2];

ll n,m;

void color(ll x,ll add,ll l,ll r,ll index)
{
	seg[index].same=true;
	seg[index].sum+=add*(r-l+1);
	seg[index].col=x;
	seg[index].add+=add;
}

void pushup(ll l,ll r,ll index)
{
	seg[index].sum=seg[index<<1].sum+seg[index<<1|1].sum;
	if(seg[index<<1].same&&seg[index<<1|1].same&&seg[index<<1].col==seg[index<<1|1].col)
	{
		seg[index].same=true;
		seg[index].col=seg[index<<1].col;
	}
	else seg[index].same=false;
}

void pushdown(ll l,ll r,ll index)
{
	ll m=(l+r)>>1;
	if(seg[index].add)
	{
		color(seg[index].col,seg[index].add,lc);
		color(seg[index].col,seg[index].add,rc);
		seg[index].add=0;
	}
}

void build(ll l,ll r,ll index)
{
	ll m=(l+r)>>1;
	if(l==r)
	{
		seg[index].same=true;
		seg[index].col=l;
		seg[index].sum=0;
		return;
	}
	build(lc);
	build(rc);
	pushup(l,r,index);
}

void update(ll L,ll R,ll x,ll l,ll r,ll index)
{
	ll m=(l+r)>>1;
	if(L==l&&R==r&&seg[index].same)
	{
		color(x,abs(seg[index].col-x),l,r,index);
		return;
	}
	pushdown(l,r,index);
	if(R<=m)update(L,R,x,lc);
	else if(L>m)update(L,R,x,rc);
	else
	{
		update(L,m,x,lc);
		update(m+1,R,x,rc);
	}
	pushup(l,r,index);
}

ll query(ll L,ll R,ll l,ll r,ll index)
{
	ll m=(l+r)>>1;
	if(L==l&&R==r)return seg[index].sum;
	pushdown(l,r,index);
	if(R<=m)return query(L,R,lc);
	else if(L>m)return query(L,R,rc);
	else return query(L,m,lc)+query(m+1,R,rc);
}

int main()
{
	scanf("%I64d%I64d",&n,&m);
	build(1,n,1);
	while(m--)
	{
		ll op,a,b,c;
		scanf("%I64d",&op);
		if(op==1)
		{
			scanf("%I64d%I64d%I64d",&a,&b,&c);
			update(a,b,c,1,n,1);
		}
		else
		{
			scanf("%I64d%I64d",&a,&b);
			printf("%I64d\n",query(a,b,1,n,1));
		}
	}
	return 0;
}

Codeforces 444C(线段树)

时间: 2024-10-25 07:46:31

Codeforces 444C(线段树)的相关文章

Codeforces 384E 线段树+dfs序

题目链接:点击打开链接 题意: 给定n个点,m个询问的无向树(1为根) 下面n个数表示每个点的权值 下面n-1行给出树 操作1:x点权值+v, x的第 i & 1 的儿子-v, 第 !(i&1) 的儿子+v 操作2:询问x点权值 dfs把树转成序列 根据深度把点分成2组 分别用线段树维护.. 然后Y一下 #include<stdio.h> #include<string.h> #include<iostream> #include<algorith

Codeforces 446C 线段树 递推Fibonacci公式

聪哥推荐的题目 区间修改和区间查询,但是此题新颖之处就在于他的区间修改不是个定值,而是从L 到 R 分别加 F1.F2....Fr-l+1 (F为斐波那契数列) 想了一下之后,觉得用fib的前缀和来解决,每次做懒惰标记记录下当前区间是从哪个L开始加起的,敲了一半之后发现有问题,就跟上次遇到的懒惰标记问题一样,这是个覆盖性的懒惰标记,每次向下传递后,都要先清除孩子的,清除孩子的也有可能要清除son's son,所以要一直pushdown下去,否则就会错,但这样就会超时. 能不能有个累加型的标记让我

Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论

Bash and a Tough Math Puzzle CodeForces 914D 线段树+gcd数论 题意 给你一段数,然后小明去猜某一区间内的gcd,这里不一定是准确值,如果在这个区间内改变一个数的值(注意不是真的改变),使得这个区间的gcd是小明所猜的数也算小明猜对.另一种操作就是真的修改某一点的值. 解题思路 这里我们使用线段树,维护区间内的gcd,判断的时候需要判断这个区间的左右子区间的gcd是不是小明猜的数的倍数或者就是小明猜的数,如果是,那么小明猜对了.否则就需要进入这个区间

Codeforces 833B 线段树优化 dp

Codeforces  833B  The Bakery 题意: n 个数要分成 k 块,每块的价值是其不同数的个数,问价值和最大是多少. tags: dp[i][j]表示前 j 个数分成 i 块的最大权值和,转移: dp[i][j] = max( dp[i-1][k] + val[k+1][j] ) , k是 1~j . 但这个过程其实并不好转移,要利用累加的特点,用线段树进行优化 (感觉我不看题解是想不到的,2333) 大概就是,对于第 i 层,我们假定已经知道了第 i-1 层,也就是求出了

Codeforces 938G 线段树分治 线性基 可撤销并查集

Codeforces 938G Shortest Path Queries 一张连通图,三种操作 1.给x和y之间加上边权为d的边,保证不会产生重边 2.删除x和y之间的边,保证此边之前存在 3.询问x到y的路径异或最小值 保证图在任意时刻连通 首先连通图路径异或相当于从x到y的任意一条路径再异或上若干个环得到的,只要在dfs过程中把非树边成的环丢到线性基里就好了,其他环一定可以通过这些环异或组合出来 有加边删边操作怎么做呢?线段树时间分治!注意到不能保证在线段树的任意一个节点图是连通的,需要用

codeforces 589G:线段树+二分

离线做 先按照t[]建线段树,维护区间的有效天数以及可用时间 然后把t[]从小到达排序,记得记录t中元素在线段树中的位置 把询问按照d从小到大排序,依次考虑 由于按照d排序,所以当前询问肯定是d最短的,我们在t数组中找到大于当前d的第一个元素位置,把这之前的元素全部从线段树中删除,表示这些天数无效 因为当前d已经是最小,所以删除对后续不会有影响 二分一个天数,查找0~mid天一共的工作时间(工作时间=总可用时间-准备时间*有效天数) #include"cstdio" #include&

CodeForces 343D 线段树维护dfs序

给定一棵树,初始时树为空 操作1,往某个结点注水,那么该结点的子树都注满了水 操作2,将某个结点的水放空,那么该结点的父亲的水也就放空了 操作3,询问某个点是否有水 我们将树进行dfs, 生成in[u], 访问结点u的时间戳,out[u],离开结点u的时间戳 每个结点的in值对应在线段树中的区间的一点 那么对于操作1, 只要将区间[in[u],out[u]] 的值都改为1, 但是如果区间[in[u],out[u]] 原先存在为0的点,那么父区间肯定是空的,这个操作不能 改变父区间的状态,所以需要

Codeforces 558E 线段树处理字符串内排序

给出长度为n的字符串,m个操作. 每一个操作有三个值 l,r,op. op==1,表示将字符串中[ l ,r ]的部分依照升序排列. op==0,表示将字符串中[ l ,r ]的部分依照降序排列. 输出终于的字符串 按小写字母建26颗线段树 对于每次改动,先记录[l,r]区间内各个字母出现的次数,并对对应区间清空,然后依照升序或者降序从新更新 #include "stdio.h" #include "string.h" char str[100010]; int n

codeforces 997E(线段树)

分析: 首先考虑如何计算整个数组有多少个good区间 容易发现一个区间是good区间当且仅当max-min-len=-1,且任意区间max-min-len>=-1 我们可以枚举右端点,然后维护前面每个位置到当前右端点的max-min-len值,容易发现我们只需要维护区间最小值和最小值的个数就行了,于是用线段树即可 于是我们可以得到以某个点为右端点的时候合法区间总数,那么我们把每次的结果加起来,就得到了整个数组有多少个good区间 每次右端点移动怎么更新呢?显然我们只需要用一个max单调栈,一个m

Blog Post Rating CodeForces - 806E (线段树二分)

题目链接 题目大意: 有一个博客, 初始分数为$0$, 有$n$个人, 第$i$个人有一个期望值$a_i$, 如果第$i$个人浏览博客时,博客赞数高于$a_i$博客分数$-1$, 低于$+1$, 相等不变, 对于每个$i$, 求出$[1,i]$的人按任意顺序浏览博客后最大分数. 题解: 首先, 用贪心可以知道所有人按期望升序排列, 最后得分一定最大 由于期望有负数, 博客分数一定是先减后增的, 然后对这两段分类讨论 对于递减的段, 最后分数为递增递减的临界值 假设临界值为$x$, 设比$x$小的