UVA 12436 Rip Van Winkle's Code(线段树区间更新)
2015-07-31 16:09
253 查看
题意:
对于长度为250000的区间,给了你四种操作:操作A,从st到ed这段区间内的数,分别加上1,2,…,st-ed+1。
操作B,从st到ed这段区间内的数,分别加上,st-ed+1,st-ed,…,1。
操作C,将st到ed这段区间内的数赋值成x。
操作S,查询st到ed的这段区间内的数的总和。
解析:
因为操作A和操作B都是操作的实际上都是等差数列,所以可以一起考虑。对于操作AB,在线段树的结点中记录了这个区间的首项a1,同时记录了这段区间内的公差d。
对于操作C,在线段树的结点内,用一个cover表示当前区间内的数是否全部相同,并且还用一个val表示如果在区间里的数完全相同的时候,即cover=1时,这个数是多少。
容易得到,等差数列相加还是等差数列,所以可以对一个区间进行多次的AB操作。
对于C操作,因为强制将区间内的赋值成x,所以之前的AB操作全部失效,即这时候应该把表示AB操作的几个变量,a1和d全部赋值为零。
当向子区间传递记录的值的时候,应该优先C操作的标记,因为当操作AB和操作C的标记同时存在的时候,一定是发生在先进行了操作C,再进行了操作AB。
mymy codecode
[code]#include <cstdio> #include <cstring> #include <algorithm> #define ls (o<<1) #define rs (o<<1|1) #define lson ls, L, M #define rson rs, M+1, R using namespace std; typedef long long ll; const int N = 250001; struct Node { int L, R; ll a1, d, val, sum; bool cover; Node() { a1 = d = val = sum = cover = 0;} ll length() { return R - L + 1; } } node[N<<2]; void pushUp(int o) { node[o].sum = node[ls].sum + node[rs].sum; } void pushDown(int o) { if(node[o].cover) { node[ls].cover = node[rs].cover = true; node[ls].val = node[rs].val = node[o].val; node[ls].sum = node[ls].length() * node[o].val; node[rs].sum = node[rs].length() * node[o].val; node[ls].a1 = node[ls].d = node[rs].a1 = node[rs].d = 0; node[o].val = node[o].cover = 0; } if(node[o].a1 || node[o].d) { ll d = node[o].d; ll len1 = node[ls].length(), len2 = node[rs].length(); ll a1 = node[o].a1, a2 = a1 + len1 * d; node[ls].a1 += a1; node[ls].d += d; node[ls].sum += a1 * len1 + len1 * (len1-1)/2 * d; node[rs].a1 += a2; node[rs].d += d; node[rs].sum += a2 * len2 + len2 * (len2-1)/2 * d; node[o].a1 = node[o].d = 0; } } void build(int o, int L, int R) { node[o] = Node(); node[o].L = L, node[o].R = R; if(L == R) return ; int M = (L + R)/2; build(lson); build(rson); pushUp(o); } void modify(int o, int L, int R, int ql, int qr, ll d) { if(ql <= L && R <= qr) { ll a1 = (d == 1) ? (L - ql + 1) : (qr - L + 1); ll n = node[o].length(); node[o].a1 += a1; node[o].d += d; node[o].sum += a1 * n + n * (n-1)/2 * d; return ; } pushDown(o); int M = (L + R)/2; if(ql <= M) modify(lson, ql, qr, d); if(qr > M) modify(rson, ql, qr, d); pushUp(o); } void setValue(int o, int L, int R, int ql, int qr, ll val) { if(ql <= L && R <= qr) { node[o].sum = node[o].length() * val; node[o].val = val; node[o].cover = true; node[o].a1 = node[o].d = 0; return ; } pushDown(o); int M = (L + R)/2; if(ql <= M) setValue(lson, ql, qr, val); if(qr > M) setValue(rson, ql, qr, val); pushUp(o); } ll query(int o, int L, int R, int ql, int qr) { if(ql <= L && R <= qr) return node[o].sum; pushDown(o); int M = (L + R)/2; ll ret = 0; if(ql <= M) ret += query(lson, ql, qr); if(qr > M) ret += query(rson, ql, qr); return ret; } int main() { build(1, 1, N); int T; scanf("%d", &T); char oper[5]; int ql, qr, val; while(T--) { scanf("%s%d%d", oper, &ql, &qr); if(oper[0] == 'A') { modify(1, 1, N, ql, qr, 1); }else if(oper[0] == 'B') { modify(1, 1, N, ql, qr, -1); }else if(oper[0] == 'C') { scanf("%d", &val); setValue(1, 1, N, ql, qr, val); }else if(oper[0] == 'S') { printf("%lld\n", query(1, 1, N, ql, qr)); } } return 0; }
相关文章推荐
- Unity AssetBundle爬坑手记
- Python下用Google Map查询地址的经纬度
- C++对象模型——程序转化语意学(第二章)
- 【CSS学习】CSS 背景
- 多线程与java运行环境的总结
- COJ0702 数学(三)
- (算法)Hanoi Problem汉诺塔问题
- Java遍历输出指定目录、树形结构所有文件包括子目录下的文件
- [转]关于iOS多线程,你看我就够了
- Linux的网络协议中的网卡缓冲区
- ThinkPHP框架 去除header中的X-Powered-By属性
- 2012Web负载测试
- POJ 1547:Clay Bully
- byte[],inputstream互转
- 路径的学习
- 区间DP的主要思路
- python初学小结1
- 【Android本地开发技术:媒体开发】YUV格式解析
- 人生何为贵?
- using werkzeug to build a shorly url app