<html>
题意:
一段区间a一開始是1、2、3、4……n这种 每次1操作能够将[l,r]覆盖成x 同一时候得到abs(a[i]-x)的价值 2操作查询[l,r]的价值
思路:
线段树 又是一道加深线段树理解的题
操作2是简单的求和 线段树基本操作 难点在操作1
用cov表示该区间的值(假设为0说明是混合区间) 用val表示该区间的价值和
那么在更新时就不不过找到 tree[i].l==l&&tree[i].r==r 就停止了 而是继续向下递归 直到一段区间的cov>0才结束
之所以这么做是由于要将x覆盖到之前覆盖过的连续的区间(事实上就是将曾经混合的区间合并成一个) 这是更新val所必须的
但如此做了我们会发现val仅仅计算到了更新过的位置 无法将这次更新down下去 那么就须要设置一个lazy标志
lazy记录该区间还没有被down下去的价值
代码:
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define N 101000 #define L(x) (x<<1) #define R(x) ((x<<1)|1) typedef __int64 ll; int n,m; struct node { int l,r,cov; ll val,lazy; }tree[N*4]; ll ans; int abs(int x) { if(x<0) return -x; return x; } void up(int i) { tree[i].val=tree[L(i)].val+tree[R(i)].val; } void down(int i) { if(tree[i].cov) { tree[L(i)].cov=tree[i].cov; tree[R(i)].cov=tree[i].cov; tree[i].cov=0; } if(tree[i].lazy) { tree[L(i)].lazy+=tree[i].lazy; tree[L(i)].val+=tree[i].lazy*(tree[L(i)].r-tree[L(i)].l+1); tree[R(i)].lazy+=tree[i].lazy; tree[R(i)].val+=tree[i].lazy*(tree[R(i)].r-tree[R(i)].l+1); tree[i].lazy=0; } } void init(int l,int r,int i) { tree[i].l=l; tree[i].r=r; tree[i].val=tree[i].lazy=0; if(l==r) { tree[i].cov=l; return ; } int mid=(l+r)/2; init(l,mid,L(i)); init(mid+1,r,R(i)); } void solve(int i,int key) { if(tree[i].cov) { tree[i].lazy+=abs(key-tree[i].cov); tree[i].val+=(ll)(abs(key-tree[i].cov))*(tree[i].r-tree[i].l+1); tree[i].cov=key; return ; } else { down(i); solve(L(i),key); solve(R(i),key); up(i); } tree[i].cov=key; } void update(int l,int r,int i,int key) { if(tree[i].l==l&&tree[i].r==r) { solve(i,key); return ; } down(i); int mid=(tree[i].l+tree[i].r)/2; if(r<=mid) update(l,r,L(i),key); else if(l>mid) update(l,r,R(i),key); else { update(l,mid,L(i),key); update(mid+1,r,R(i),key); } up(i); } void query(int l,int r,int i) { if(tree[i].l==l&&tree[i].r==r) { ans+=tree[i].val; return ; } down(i); int mid=(tree[i].l+tree[i].r)/2; if(r<=mid) query(l,r,L(i)); else if(l>mid) query(l,r,R(i)); else { query(l,mid,L(i)); query(mid+1,r,R(i)); } up(i); } int main() { int p,l,r,w; scanf("%d%d",&n,&m); init(1,n,1); while(m--) { scanf("%d%d%d",&p,&l,&r); if(p==1) { scanf("%d",&w); update(l,r,1,w); } else { ans=0; query(l,r,1); printf("%I64d\n",ans); } } return 0; }
版权声明:本文为博主原创文章,未经博主同意不得转载。
举报
- 本文已收录于下面专栏:
相关文章推荐
-
codeforces 424C. Magic Formulas (异或规律)
链接:http://codeforces.com/problemset/problem/424/C 题目: People in the Tomskaya region like magic fo...- theArcticOcean
- 2015-12-22 16:27
- 447
-
Codeforces 444C(线段树)
区间颜色不一致就更新究竟。否则lazy标记 #include #include #include #include using namespace std; #define lc l,m,index...- swust_wbh
- 2014-07-07 01:24
- 795
-
CodeForces 631C Report(找规律)
题目链接:【CodeForces 631C】 长度是n的数列。m个次訪问,两种操作:1、t=1,将数列1~r从小到大排序。2、t=2,将数列1~r从大到小排列。输出最后得到的数列 假设i>j&&r...- YHYYXT
- 2016-03-05 13:51
- 698
-
Codeforces 460C Present(二分)
题目链接:Codeforces 460C Present 题目大意:有n盆花,能够浇m次水。每次浇水的范围为w。被浇到水的花长高1米,问说能够使最矮的花的最高值是多少 解题思路:二分答案。...- u011328934
- 2014-08-25 00:07
- 783
-
codeforces 414 c
题意: 给出一个长度为n- u013573306
- 2014-04-16 15:55
- 460
-
Codeforces 479C Exams(贪心)
题目链接:Codeforces 479C Exams 题目大意:期末考试了,有个人希望尽快考全然部的科目。于是和每一个科任老师单独沟通。最后每一个科任老师愿意给额 外给定一个时间单独给她考试。...- u011328934
- 2014-11-02 23:30
- 915
-
CodeForces 140C 贪心+优先队列
Description 如今来做雪人,每一个雪人由三个不同大小的雪球构成:一个大的。一个中等的,一个小的。如今有 n 个雪球半径分别为 r1, r2, ..., rn. 为了做雪人。三个雪球的大小必须...- HowardEmily
- 2016-11-25 21:39
- 205
-
codeforces-757-【B、C思维】
题目链接:点击打开链接 A. Gotta Catch Em' All! time limit per test 1 second memory limit per te...- wang907553141
- 2017-01-16 00:02
- 317
-
Codeforces 466C Number of Ways(高效)
题目链接:Codeforces 466C Number of Ways 题目大意:给定一个序列。要求分成三段,每段和同样,问有多少种拆分方法。 解题思路:将所有前缀和为sum3的位置所有记...- u011328934
- 2014-09-24 15:46
- 770
-
Codeforces 444C DZY Loves Colors 线段树区间更新
// Codeforces 444C DZY Loves Colors 线段树区间更新 // 题目链接: // http://codeforces.com/problemset/pr...- TIMELIMITE
- 2016-10-12 20:18
- 171
收藏助手
不良信息举报
0条评论