您的位置:首页 > 其它

hdu4578 Transformation

2015-11-03 22:41 337 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4578

题目大意:n个数(初始为0)m个操作,操作类型有4种,操作1把区间的每个数+a,操作2把区间的每个数*a.,操作3把区间的每个数=a,操作4,查询区间每个数p次方的和(1<=p<=3)

解:

线段树解决,考虑的问题有两个:

1、赋值操作一定放在前面,然后有 先+后* 和 先*后+ 效果不一样

2、p次方和

对于问题一,采用先*后+的方式,这样在加入一个乘法标记的时候只用给之前的加标记乘上新标记的数即可

对于问题二,把(a+b)^2 和 (a+b)^3 展开,就知道怎么处理了

/*
* Problem:
* Author:  SHJWUDP
* Created Time:  2015/11/3 星期二 15:20:05
* File Name: 1001.cpp
* State:
* Memo:
*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#include <list>

using namespace std;

const int MOD=1e4+7;

struct SegmentTree {
struct Node {
vector<long long> sum;
vector<long long> delay;
Node():sum(3), delay(3){ delay[1]=1; }
void relax() {
for(auto & x : sum) x%=MOD;
for(auto & x : delay) x%=MOD;
}
};
int n;
vector<Node> c;
SegmentTree(int _n):n(_n),c(_n<<2){}
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
void deal(Node & o, pair<int, int> p, int range) {
auto & d=o.delay;
long long b1=p.second, b2=b1*b1, b3=b2*b1;
switch(p.first) {
case 0:
{
long long a1=o.sum[0], a2=o.sum[1];
o.sum[2]+=3*a1*b2+3*a2*b1+b3*range;
o.sum[1]+=2*a1*b1+b2*range;
o.sum[0]+=b1*range;
d[0]+=b1;
break;
}
case 1:
o.sum[2]*=b3;
o.sum[1]*=b2;
o.sum[0]*=b1;
d[0]*=b1;
d[1]*=b1;
break;
case 2:
o.sum[2]=b3*range;
o.sum[1]=b2*range;
o.sum[0]=b1*range;
d[0]=0; d[1]=1;
d[2]=b1;
break;
}
o.relax();
}
void pushDown(int l, int m, int r, int rt) {
for(int i=2; i>=0; --i) {
if(!c[rt].delay[i]) continue;
if(i==1 && c[rt].delay[i]==1) continue;
deal(c[rt<<1], {i, c[rt].delay[i]}, m-l+1);
deal(c[rt<<1|1], {i, c[rt].delay[i]}, r-m);
}
c[rt].delay={0, 1, 0};
}
void pushUp(int rt) {
for(int i=0; i<3; ++i) {
c[rt].sum[i]=(c[rt<<1].sum[i]+c[rt<<1|1].sum[i])%MOD;
}
}
void update(int L, int R, pair<int, int> x, int l, int r, int rt) {
if(L<=l && r<=R) {
deal(c[rt], x, r-l+1);
} else {
int m=(l+r)>>1;
pushDown(l, m, r, rt);
if(L<=m) update(L, R, x, lson);
if(m<R) update(L, R, x, rson);
pushUp(rt);
}
}
int query(int L, int R, int x, int l, int r, int rt) {
if(L<=l && r<=R) {
return c[rt].sum[x];
} else {
int m=(l+r)>>1;
pushDown(l, m, r, rt);
int ret=0;
if(L<=m) ret=query(L, R, x, lson);
if(m<R) ret=(ret+query(L, R, x, rson))%MOD;
return ret;
}
}
};

int main() {
#ifndef ONLINE_JUDGE
freopen("in", "r", stdin);
freopen("out", "w", stdout);
#endif
int n, m;
while(scanf("%d%d", &n, &m), n||m) {
SegmentTree st(n);
while(m--) {
int op, a, b, c;
scanf("%d%d%d%d", &op, &a, &b, &c);
--a; --b;
//        cout<<"<----------------->"<<endl;
if(op==4) {
printf("%d\n", st.query(a, b, c-1, 0, st.n-1, 1));
} else {
st.update(a, b, {op-1, c}, 0, st.n-1, 1);
}
}
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: