您的位置:首页 > 其它

HDU-4578:Transformation(有条件的延迟标记)

2017-08-08 20:59 260 查看
题目链接:点击打开链接

题目大意:

对一段区间进行操作,一共有四种操作

(1)   将一段区间内的数都加上c

(2)   将一段区间内的数都乘上c

(3)   将一段区间的数都变成c

(4)   统计一段区间内所有数的 p 次方的和。但是 p只有 1到3

解题思路:

看到是ICPC的题目,就决定自己好好做。上来一看8秒,我懂了,直接延迟更新,查询的时候再搜到子节点,然后加个次方,然后t了,

然后想了一下,恩,不对。不能这样,太耗时了,后来注意到p的范围只有1到3,惊了,遂决定维护三个值,分别表示p分别为 1 2 3时候的和,但是这样延迟更新就很麻烦,我 想都这样了,那就只延迟更新 3 操作吧。恩,然后t了。

我去,还能怎么简化,想了想,如果这段区间先执行过操作3的话并打了标记,那么操作1的变化值可以直接累加上去,恩,我找到了解题的关键,写上去,t了。

我日,仔细想了半天,真tm智障啊,(2)操作和(1)操作不是一样的嘛,适用于(1)的更新方法同样适用于(2)啊,同样可以延迟啊,加上以后,然后wa了。

真没辙了,开始仔细看代码,感觉自己代码绝对没有错误。检查许久,我终于在不起眼的地方发现了错误。超级容易漏掉的地方!!!

就是每次延迟更新的累加值一定要取余,一定要取余!!! 遂AC

然后删掉了一些自己认为不重要的地方,想让代码好看点,然后wa了。我~~那就这样吧,

总体思路就是如果一段区间之前被操作3打过标记的话,那么再在这段区间进行类似(1)(2)的操作就是可以直接累加到变化值里,就跟正常的延迟更新一样,如果没有的话,就直接更新到子节点。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#include <set>
#include <functional>
#define rank ra
#define lson rt<<1
#define rson rt<<1|1
#define pb push_back
using namespace std;
typedef long long ll;
const int INF = 1e9 + 5;
const int mod=10007;
int n,m;
int ans;
struct node
{
int l,r,mid;
int lazy; //是否进行过操作3同时也是延迟更新的标记
int c; //延迟更新的变化值
int sum1; //次方分别1到3的和
int sum2;
int sum3;
}t[500000];
void pushup(int rt)
{
t[rt].sum1=(t[lson].sum1+t[rson].sum1)%mod;
t[rt].sum2=(t[lson].sum2+t[rson].sum2)%mod;
t[rt].sum3=(t[lson].sum3+t[rson].sum3)%mod;
}
void pushdown(int rt)
{
if(t[rt].lazy) //延迟更新,因为操作3的特性,所以直接更新
{
t[lson].sum1=t[rt].c*(t[lson].r-t[lson].l+1)%mod;
t[lson].sum2=t[rt].c*t[lson].sum1%mod;
t[lson].sum3=t[rt].c*t[lson].sum2%mod;
t[rson].sum1=t[rt].c*(t[rson].r-t[rson].l+1)%mod;
t[rson].sum2=t[rt].c*t[rson].sum1%mod;
t[rson].sum3=t[rt].c*t[rson].sum2%mod;
t[rson].c=t[lson].c=t[rt].c;
t[rson].lazy=t[lson].lazy=t[rt].lazy;
t[rt].c=t[rt].lazy=0;
}
}
void build(int l,int r,int rt)
{
int mid=(l+r)>>1;
t[rt].l=l;t[rt].r=r;
t[rt].mid=mid;
t[rt].sum1=t[rt].sum2=t[rt].sum3=t[rt].lazy=t[rt].c=0;
if(l==r)
return ;
build(l,mid,lson);
build(mid+1,r,rson);
pushup(rt);
}
void update(int l,int r,int flag,int c,int rt)
{

if(l<=t[rt].l&&t[rt].r<=r&&(t[rt].lazy==1||flag==3)) //是3操作或者是1 2操作但是执行过操作3
{
if(flag==3)
{
t[rt].lazy=1;
t[rt].c=c;
}
if(flag==1) //变化值累加
t[rt].c += c;
if(flag==2)
t[rt].c=t[rt].c*c;
t[rt].c=t[rt].c%mod; //注意一定要取余
t[rt].sum1=t[rt].c*(t[rt].r-t[rt].l+1)%mod;
t[rt].sum2=t[rt].c*t[rt].sum1%mod;
t[rt].sum3=t[rt].c*t[rt].sum2%mod;
return ;
}
if(flag!=3&&l<=t[rt].l&&t[rt].r<=r&&t[rt].l==t[rt].r) //没有的话就更新到子节点
{
if(flag==1)
t[rt].sum1=(t[rt].sum1+c)%mod;
if(flag==2)
t[rt].sum1=(t[rt].sum1*c)%mod;
t[rt].sum2=t[rt].sum1*t[rt].sum1%mod;
t[rt].sum3=t[rt].sum2*t[rt].sum1%mod;
return ;
}
pushdown(rt);
if(l<=t[rt].mid)
update(l,r,flag,c,lson);
if(r>t[rt].mid)
update(l,r,flag,c,rson);
pushup(rt);
}
void query(int l,i
9933
nt r,int c,int rt) //正常查询
{
if(l<=t[rt].l&&t[rt].r<=r)
{
if(c==1)
ans += t[rt].sum1;
if(c==2)
ans += t[rt].sum2;
if(c==3)
ans += t[rt].sum3;
ans=ans%mod;
return ;
}
pushdown(rt);
if(l<=t[rt].mid)
query(l,r,c,lson);
if(r>t[rt].mid)
query(l,r,c,rson);
pushup(rt);
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(n==0&&m==0)
break;
build(1,n,1);
int q,l,r,c;
for(int i=0;i<m;i++)
{
scanf("%d%d%d%d",&q,&l,&r,&c);
if(q>=1&&q<=3)
update(l,r,q,c,1);
if(q==4)
{
ans=0;
query(l,r,c,1);
printf("%d\n",ans%mod);
}
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: