首页 > 其他 > 详细

hdu 4578 Transformation

时间:2014-08-19 22:30:35      阅读:404      评论:0      收藏:0      [点我收藏+]

http://acm.hdu.edu.cn/showproblem.php?pid=4578


又做了一道好题。。

有三种操作:

1 a b c [a,b]加上c

2 a b c [a,b]乘上c

3 a b c [a,b]变为c

4 a b c 求[a,b]的c次方和(1<=c<=3)


这题首先需要解决的第一个问题是加上或乘上一个数对这个区间的c次方和分别产生什么改变,很简单,一化简就能得到。

第二个问题是当一段区间上既有乘又有加的lazy时应该怎么向下推送,因为一段区间上只能有一个lazy,我起初做的是先将有lazy的标记向下传,直到不冲突为止,然后更新这个区间的lazy,后来无数次的wa。代码太长了,简直无法debug。

同学说要找到这两个lazy的关系,即可以把每个数看做mult * x + add。加上一个数y时,add+= y,乘上一个数y时,mult *= y,add *= y。这样就解决了先加后乘和先乘后加的问题了,感觉好机智,mark。


#include <stdio.h>
#include <iostream>
#include <map>
#include <set>
#include <list>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
//#define LL long long
#define LL __int64
#define eps 1e-12
#define PI acos(-1.0)
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100010;
const int mod = 10007;

struct node
{
    int l,r;
    int mult,add;
    int s[4];
} tree[maxn*4];


void build(int v, int l, int r)
{
	tree[v].l = l;
	tree[v].r = r;
	tree[v].mult = 1;
	tree[v].add = 0;
	tree[v].s[1] = tree[v].s[2] = tree[v].s[3] = 0;
	if(l == r)
		return;
	int mid = (l+r)>>1;
	build(v*2,l,mid);
	build(v*2+1,mid+1,r);
}
void cal(int v,int mult, int add)
{
	int len = tree[v].r - tree[v].l + 1;

	tree[v].s[1] = tree[v].s[1] * mult%mod;
	tree[v].s[2] = tree[v].s[2] * mult%mod*mult%mod;
	tree[v].s[3] = tree[v].s[3] * mult%mod*mult%mod*mult%mod;
	tree[v].mult = (tree[v].mult * mult)%mod;
	tree[v].add = (tree[v].add * mult)%mod;

	tree[v].s[3] = (tree[v].s[3] + 3*add%mod*add%mod*tree[v].s[1]%mod)%mod;
	tree[v].s[3] = (tree[v].s[3] + 3*add%mod*tree[v].s[2]%mod)%mod;
	tree[v].s[3] = (tree[v].s[3] + len*add%mod*add%mod*add%mod)%mod;
	tree[v].s[2] = (tree[v].s[2] + 2*add%mod*tree[v].s[1]%mod)%mod;
	tree[v].s[2] = (tree[v].s[2] + len*add%mod*add%mod)%mod;
	tree[v].s[1] = (tree[v].s[1] + len*add%mod)%mod;
	tree[v].add = (tree[v].add + add)%mod;
}

void push_down(int v)
{
	if(tree[v].l == tree[v].r)
		return;
	cal(v*2,tree[v].mult,tree[v].add);
	cal(v*2+1,tree[v].mult,tree[v].add);
	tree[v].mult = 1;
	tree[v].add = 0;
}

void push_up(int v)
{
	int ls = v*2,rs = v*2+1;
	tree[v].s[1] = (tree[ls].s[1] + tree[rs].s[1])%mod;
	tree[v].s[2] = (tree[ls].s[2] + tree[rs].s[2])%mod;
	tree[v].s[3] = (tree[ls].s[3] + tree[rs].s[3])%mod;
}

void update(int v, int l, int r, int mult, int add)
{
	if(tree[v].l == l && tree[v].r == r)
	{
		cal(v,mult,add);
		return;
	}

	push_down(v);

	int mid = (tree[v].l + tree[v].r) >> 1;

	if(r <= mid)
		update(v*2,l,r,mult,add);
	else if(l > mid)
		update(v*2+1,l,r,mult,add);
	else
	{
		update(v*2,l,mid,mult,add);
		update(v*2+1,mid+1,r,mult,add);
	}
	push_up(v);
}

int query(int v, int l, int r,int p)
{
	if(tree[v].l == l && tree[v].r == r)
	{
		return tree[v].s[p];
	}
	push_down(v);
	int mid = (tree[v].l + tree[v].r) >> 1;
	if(r <= mid)
		return query(v*2,l,r,p);
	else if(l > mid)
		return query(v*2+1,l,r,p);
	else
		return (query(v*2,l,mid,p) + query(v*2+1,mid+1,r,p))%mod;
}

int main()
{
    int n,m;
    int op,x,y,c;
    while(~scanf("%d %d",&n,&m))
    {
        if(n == 0 && m == 0) break;
        build(1,1,n);
        while(m--)
        {
            scanf("%d %d %d %d",&op,&x,&y,&c);
            if(op == 1)
				update(1,x,y,1,c);
			else if(op == 2)
				update(1,x,y,c,0);
			else if(op == 3)
				update(1,x,y,0,c);
            else
                printf("%d\n",query(1,x,y,c)%mod);
        }
    }
    return 0;
}


hdu 4578 Transformation,布布扣,bubuko.com

hdu 4578 Transformation

原文:http://blog.csdn.net/u013081425/article/details/38688579

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!