这个题是线段树区间更新,区间查询
一个语句顺序错了,我弄了2个小时才找到(细心才是王道)
#include<stdio.h>
#include<string.h>
#include<string>
#include<algorithm>
#include<iostream>
#define maxn 100005
using namespace std;
struct Node
{
int left,right;
int val,lazy;
//val是值,lazy是延迟标记
} tree[maxn<<2];
int A[maxn];
void build(int L,int R,int rt)//创建
{
tree[rt].left=L;
tree[rt].right=R;
tree[rt].lazy=0;//就是这,浪费了我2个小时
if(L==R)
{
tree[rt].val=A[L];
return ;
}
int m=(L+R)>>1;
build(L,m,rt<<1);
build(m+1,R,rt<<1|1);
tree[rt].val=tree[rt<<1].val+tree[rt<<1|1].val;
}
void updata(int rt,int i,int val)//单点更新
{
if(tree[rt].left==tree[rt].right)
{
tree[rt].val=val;
return ;
}
int m=(tree[rt].right+tree[rt].left)>>1;
if(i<=m) updata(rt<<1,i,val);
else updata(rt<<1|1,i,val);
tree[rt].val=tree[rt<<1].val+tree[rt<<1|1].val;
}
void pushdown(int rt)//根据延迟标记向下更新
{
if(tree[rt].lazy>0)
{
tree[rt<<1].lazy=tree[rt].lazy;
tree[rt<<1|1].lazy=tree[rt].lazy;
tree[rt<<1].val=tree[rt].lazy*(tree[rt<<1].right-tree[rt<<1].left+1);
tree[rt<<1|1].val=tree[rt].lazy*(tree[rt<<1|1].right-tree[rt<<1|1].left+1);
tree[rt].lazy=0;
}
}
void updata2(int l,int r,int rt,int val)//区间更新
{
if(r<tree[rt].left||l>tree[rt].right)return ;
if(l<=tree[rt].left&&r>=tree[rt].right)
{
tree[rt].lazy=val;//加上延迟标记
tree[rt].val=val*(tree[rt].right-tree[rt].left+1);//更新这个区间的值
return ;
}
pushdown(rt);
int mid=(tree[rt].left+tree[rt].right)>>1;
if(l<=mid) updata2(l,r,rt<<1,val);
if(r>mid)updata2(l,r,rt<<1|1,val);
tree[rt].val=tree[rt<<1].val+tree[rt<<1|1].val;
}
//根据以上pushdown函数和updata2函数可以看出,具有lazy标记不为0的节点,这个节点的值已经是更新过的,只需要将更新标记下移并且一次只更新左儿子和右儿子的值
//孙子节点的值下一次再更新
query(int l,int r,int rt)
{
if(l<=tree[rt].left&&r>=tree[rt].right)
{
return tree[rt].val;
}
int sum=0;
pushdown(rt);
int m=(tree[rt].left+tree[rt].right)>>1;
if(l>m)sum+=query(l,r,rt<<1|1);
else if(r<=m)sum+=query(l,r,rt<<1);
else
{
sum+=query(l,r,rt<<1);
sum+=query(l,r,rt<<1|1);
}
return sum;
}
int main()
{
int i,j,n,k,t;
int cas=1;
int m;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&m);
int a,b,c;
int tmp;
for(i=1; i<=n; ++i)
{
A[i]=1;
}
build(1,n,1);
for(i=0; i<m; ++i)
{
scanf("%d%d%d",&a,&b,&c);
updata2(a,b,1,c);
}
printf("Case %d: The total value of the hook is %d.\n",cas++,query(1,n,1));
}
return 0;
}
/*
1
10
2
1 5 2
5 9 3
*/
/*
线段树+修改区间+询问区间
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<iostream>
#include<queue>
#include<vector>
#include<map>
#include<math.h>
typedef long long ll;
//typedef __int64 int64;
const int maxn = 100005;
const int maxm = 1005;
const int inf = 0x7FFFFFFF;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std;
#define LEFT( x ) (x<<1)
#define RIGHT( x ) ((x<<1)+1)
struct node{
int l,r,sum;
int flag;
}tree[ maxn<<2 ];
int data[ maxn ];
void pushup( int n ){
tree[ n ].sum = tree[ LEFT( n ) ].sum+tree[ RIGHT( n ) ].sum;
return ;
}
void pushdown( int n,int m ){//下标为n,这段区间有m个数
if( tree[ n ].flag!=0 ){
tree[ LEFT( n ) ].flag = tree[ RIGHT( n ) ].flag = tree[ n ].flag;
tree[ LEFT( n ) ].sum = tree[ n ].flag*(m-m/2);//tree[ n ].flag*((m+1)/2);
tree[ RIGHT( n ) ].sum = tree[ n ].flag*(m/2);//tree[ n ].flag*( m-(m+1)/2 );
tree[ n ].flag = 0;
}
return;
}
void build( int l,int r,int n ){
if( l==r ){
tree[ n ].sum = data[ l ];
tree[ n ].flag = 0;
tree[ n ].l=tree[ n ].r = l;
return ;
}
tree[ n ].flag = 0;
tree[ n ].l = l;
tree[ n ].r = r;
int mid;
mid = (l+r)>>1;
build( l,mid,LEFT( n ) );
build( mid+1,r,RIGHT( n ) );
pushup( n );
return;
}
void update( int a,int b,int c,int l,int r,int n ){
if( a==l&&b==r ){
tree[ n ].flag = c;
tree[ n ].sum = (r-l+1)*c;
return ;
}
pushdown( n,r-l+1 );
//printf("test\n");
int mid;
mid = (l+r)>>1;
if( mid>=b ) update( a,b,c,l,mid,LEFT( n ) );
else if( mid<a ) update( a,b,c,mid+1,r,RIGHT( n ));
else {
update( a,mid,c,l,mid,LEFT( n ) );
update( mid+1,b,c,mid+1,r,RIGHT( n ) );
}
pushup( n );
return ;
}
int query( int a,int b,int l,int r,int n ){
if( a==l&&b==r ){
return tree[ n ].sum;
}
pushdown( n,r-l+1 );
int mid;
mid = (l+r)>>1;
if( mid>=b ) return query( a,b,l,mid,LEFT( n ) );
else if( mid<a ) return query( a,b,mid+1,r,RIGHT( n ));
else return query( a,mid,l,mid,LEFT( n ) )+query( mid+1,b,mid+1,r,RIGHT( n ));
}
int main(){
int ca;
scanf("%d",&ca);
for( int t=1;t<=ca;t++ ){
int n;
scanf("%d",&n);
for( int i=1;i<=n;i++ ){
data[ i ] = 1;
}
build( 1,n,1 );
int op;
scanf("%d",&op);
while( op-- ){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
update( a,b,c,1,n,1 );
}
printf("Case %d: The total value of the hook is %d.\n",t,tree[ 1 ].sum);
}
return 0;
}
贴上线段树延迟标记写法:
void pushup(int index){
tree[index].sum = tree[index<<1].sum+tree[index<<1|1].sum;
tree[index].mx = max(tree[index<<1].mx,tree[index<<1|1].mx);
tree[index].mn = min(tree[index<<1].mn,tree[index<<1|1].mn);
}
void pushdown(int index){
//说明该区间之前更新过
//要想更新该区间下面的子区间,就要把上次更新该区间的值向下更新
if(tree[index].add > 0){
//替换原来的值
/*
tree[index<<1].sum = (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;
tree[index<<1|1].sum = (tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;
tree[index<<1].mx = tree[index].add;
tree[index<<1|1].mx = tree[index].add;
tree[index<<1].mn = tree[index].add;
tree[index<<1|1].mn = tree[index].add;
tree[index<<1].add = tree[index].add;
tree[index<<1|1].add = tree[index].add;
tree[index].add = 0;*/
//在原来的值的基础上加上val
tree[index<<1].sum += (tree[index<<1].r-tree[index<<1].l+1)*tree[index].add;
tree[index<<1|1].sum +=(tree[index<<1|1].r-tree[index<<1|1].l+1)*tree[index].add;
tree[index<<1].mx += tree[index].add;
tree[index<<1|1].mx += tree[index].add;
tree[index<<1].mn += tree[index].add;
tree[index<<1|1].mn += tree[index].add;
tree[index<<1].add += tree[index].add;
tree[index<<1|1].add += tree[index].add;
tree[index].add = 0;
}
}