Yuanfang is puzzled with the question below: There are n integers, a 1, a 2, …, a n. The initial values of them are 0. There are four kinds of operations. Operation 1: Add c to each number between a x and a y inclusive. In other words, do transformation a k<---a k+c, k = x,x+1,…,y. Operation 2: Multiply c to each number between a x and a y inclusive. In other words, do transformation a k<---a k×c, k = x,x+1,…,y. Operation 3: Change the numbers between a x and a y to c, inclusive. In other words, do transformation a k<---c, k = x,x+1,…,y. Operation 4: Get the sum of p power among the numbers between a x and a y inclusive. In other words, get the result of a x p+a x+1 p+…+a y p. Yuanfang has no idea of how to do it. So he wants to ask you to help him.
There are no more than 10 test cases. For each case, the first line contains two numbers n and m, meaning that there are n integers and m operations. 1 <= n, m <= 100,000. Each the following m lines contains an operation. Operation 1 to 3 is in this format: "1 x y c" or "2 x y c" or "3 x y c". Operation 4 is in this format: "4 x y p". (1 <= x <= y <= n, 1 <= c <= 10,000, 1 <= p <= 3) The input ends with 0 0.
For each operation 4, output a single integer in one line representing the result. The answer may be quite large. You just need to calculate the remainder of the answer when divided by 10007.
5 5 3 3 5 7 1 2 4 4 4 1 5 2 2 2 5 8 4 3 5 3 0 0
307 7489
题目大意:n个数,初始值为0,4种操作:
1。将某个区间所有值加上另一个值;
2。将区间所有值都乘上另一个值;
3。将区间所有值置为某个值;
4。查询区间中所有值的p次方和。
题目分析:线段树。
这题其实和这题hdu3397比较类似,不一样的是hdu3397虽然对区间也有3种操作,但是对于每个操作每个区间只有一个逻辑值。而这题就稍微麻烦些,因为有乘法和加法,二者是互斥的,先乘后加和先加后乘是不一样的。所以要维护多个标记。
我在每个节点维护了4个标记,lazy就是普通的区间更新标记,sum表示当前区间的特征值(只有当前区间lazy=1的时候才能用),multi是乘法标记,add是加法标记。
此题要注意的主要有2点:
1,叶子节点初始化的时候lazy置1;
2,无论何时,某个区间的add标记和multi标记只能存在一个,即pushdown的时候,要把子树pushdown。比赛的时候这点WA了几次,还好男神及时指出。
上代码:
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<map> #include<set> #include<string> #include<cctype> #include<vector> #include<queue> using namespace std; const int N = 100005; const int M = 10000005; const int mod = 10007; const int INF = 0x3f3f3f3f; const double eps = 1e-5; const double PI = acos(-1.0); typedef __int64 ll; int n,m; struct node { ll sum; int lazy; ll multi,add; }tree[N<<2]; void pushdown(int num) { if(tree[num].lazy) { tree[num<<1].lazy = tree[num<<1|1].lazy = 1; tree[num<<1].sum = tree[num<<1|1].sum = tree[num].sum; tree[num<<1].add = tree[num<<1|1].add = 0; tree[num<<1].multi = tree[num<<1|1].multi = 1; tree[num].lazy = 0; return; } if(tree[num].add) { if(tree[num<<1].lazy) { tree[num<<1].sum += tree[num].add; tree[num<<1].sum %= mod; } else { pushdown(num<<1); tree[num<<1].add += tree[num].add; tree[num<<1].add %= mod; } if(tree[num<<1|1].lazy) { tree[num<<1|1].sum += tree[num].add; tree[num<<1|1].sum %= mod; } else { pushdown(num<<1|1); tree[num<<1|1].add += tree[num].add; tree[num<<1|1].add %= mod; } tree[num].add = 0; } if(tree[num].multi > 1) { if(tree[num<<1].lazy) { tree[num<<1].sum *= tree[num].multi; tree[num<<1].sum %= mod; } else { pushdown(num<<1); tree[num<<1].multi *= tree[num].multi; tree[num<<1].multi %= mod; } if(tree[num<<1|1].lazy) { tree[num<<1|1].sum *= tree[num].multi; tree[num<<1|1].sum %= mod; } else { pushdown(num<<1|1); tree[num<<1|1].multi *= tree[num].multi; tree[num<<1|1].multi %= mod; } tree[num].multi = 1; } } void build(int num,int s,int e) { tree[num].add = 0; tree[num].multi = 1; tree[num].sum = 0; tree[num].lazy = 0; if(s == e) { tree[num].lazy = 1; return; } int mid = (s + e)>>1; build(num<<1,s,mid); build(num<<1|1,mid + 1,e); } void update(int num,int s,int e,int l,int r,int val,int op) { if(s == l && r == e) { if(op == 3) { tree[num].lazy = 1; tree[num].sum = val; tree[num].add = 0; tree[num].multi = 1; } else { if(tree[num].lazy) { if(op == 1) tree[num].sum += val; else tree[num].sum *= val; tree[num].sum %= mod; } else { pushdown(num); if(op == 1) { tree[num].add += val; tree[num].add %= mod; } else { tree[num].multi *= val; tree[num].multi %= mod; } } } return; } pushdown(num); int mid = (s + e)>>1; if(r <= mid) update(num<<1,s,mid,l,r,val,op); else { if(l > mid) update(num<<1|1,mid + 1,e,l,r,val,op); else { update(num<<1,s,mid,l,mid,val,op); update(num<<1|1,mid + 1,e,mid + 1,r,val,op); } } } ll query(int num,int s,int e,int l,int r,int p) { if(s == l && r == e) { if(tree[num].lazy) { ll ret = 1; while(p --) { ret *= tree[num].sum; ret %= mod; } ret *= (ll)(e - s + 1); ret %= mod; return ret; } } pushdown(num); int mid = (s + e)>>1; if(r <= mid) return query(num<<1,s,mid,l,r,p); else { if(l > mid) return query(num<<1|1,mid + 1,e,l,r,p); else { return (query(num<<1,s,mid,l,mid,p) + query(num<<1|1,mid + 1,e,mid + 1,r,p)) % mod; } } } int main() { int op,a,b,c; while(scanf("%d%d",&n,&m) != EOF) { if(n == 0 && m == 0) break; build(1,1,n); while(m --) { scanf("%d%d%d%d",&op,&a,&b,&c); if(op <= 3) update(1,1,n,a,b,c,op); else printf("%I64d\n",query(1,1,n,a,b,c)%mod); } } return 0; }
//4812MS 8492K