题目传送门
题意:有一根很长的链子,原始每一段的价值是1,接下来有很多种操作,把某一段区间内整段的价值都改成1、2或者3。所有修改之后,输出这条链子的总价值。
思路
这题还是统计区间和,但是需要注意的是这里并不能像之前区间加某个数或者区间减某个数一样。我们这里需要做的是每次修改之后,区间和更新为新价值*区间长度,懒标记直接记做这次更新的价值,而不是加上这个价值。
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
const int mod=1e9+7;
const int INF=0x7fffffff;
const ll LLINF=0x7fffffffffffffff;
const double EPS=1e-10;
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define pb push_back
#define pii pair<int,int>
#define pll pair<ll,ll>
#define debug cout<<"debug"<<endl;
#define ls p<<1
#define rs p<<1|1
//#define int long long
struct tree
{
int l,r,pre,add;
}t[N<<2];
void build(int p,int x,int y)
{
t[p].l=x;t[p].r=y;
if(x==y)
{
t[p].pre=1;
return ;
}
int mid=x+y>>1;
build(ls,x,mid);
build(rs,mid+1,y);
t[p].pre=t[ls].pre+t[rs].pre;
}
void spread(int p)
{
if(t[p].add)
{
t[ls].pre=t[p].add*(t[ls].r-t[ls].l+1);
t[rs].pre=t[p].add*(t[rs].r-t[rs].l+1);
t[ls].add=t[p].add;
t[rs].add=t[p].add;
t[p].add=0;
}
}
void change(int p,int x,int y,int z)
{
if(x<=t[p].l&&t[p].r<=y)
{
t[p].pre=z*(t[p].r-t[p].l+1);
t[p].add=z;
return ;
}
spread(p);
int mid=t[p].l+t[p].r>>1;
if(x<=mid)
change(ls,x,y,z);
if(y>mid)
change(rs,x,y,z);
t[p].pre=t[ls].pre+t[rs].pre;
}
ll ask(int p,int x,int y)
{
if(x<=t[p].l&&t[p].r<=y)
{
return t[p].pre;
}
spread(p);
int mid=t[p].l+t[p].r>>1;
ll ans=0;
if(x<=mid)
ans+=ask(ls,x,y);
if(y>mid)
ans+=ask(rs,x,y);
return ans;
}
signed main()
{
IOS;
//freopen("","r",stdin);
//freopen("","w",stdout);
int n,q;
int T;
scanf("%d",&T);
int cnt=0;
while(T--)
{
cnt++;
scanf("%d%d",&n,&q);
memset(t,0,sizeof t);
build(1,1,n);
while(q--)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
change(1,x,y,z);
}
ll res=ask(1,1,n);
printf("Case %d: The total value of the hook is %lld.\n",cnt,res);
}
}