• 题意
    • 给出一个长度为n的初始化为1的序列
    • 只有一个操作U:(l,r,d),将下标区间于[l,r]内的数改为d
    • 最后输出区间[1,n]内所有数的和
  • 题解
    • 在线段树的区间加法的基础上
    • 将+=号改为=即可
    • 另外,注意add[]的初始化以及更新的判定条件
    • 本题中d>0所以仍可以用add[p]!=0表示p的子节点尚未被更新
  • 代码
    • #include<algorithm>
      #include <iostream>
      #include   <fstream>
      #include  <cstdlib>
      #include  <cstring>
      #include  <cassert>
      #include   <cstdio>
      #include   <vector>
      #include   <string>
      #include    <cmath>
      #include    <queue>
      #include    <stack>
      #include      <set>
      #include      <map>
      using namespace std;
      #define P(a,b,c) make_pair(a,make_pair(b,c))
      #define rep(i,a,n) for (int i=a;i<=n;i++)
      #define per(i,a,n) for (int i=n;i>=a;i--)
      #define CLR(vis) memset(vis,0,sizeof(vis))
      #define MST(vis,pos) memset(vis,pos,sizeof(vis))
      #define pb push_back
      #define mp make_pair
      #define all(x) (x).begin(),(x).end()
      #define fi first
      #define se second
      #define SZ(x) ((int)(x).size())
      typedef pair<int,pair<int,int> >pii;
      typedef long long ll;
      typedef unsigned long long ull;
      const ll mod = 1000000007;
      const int INF = 0x3f3f3f3f;
      ll gcd(ll a, ll b) {
      	return b ? gcd(b, a%b) : a;
      }
      template<class T>inline void gmax(T &A, T B) {
      	(A<B)&&(A=B);//if(B>A)A=B;
      }
      template<class T>inline void gmin(T &A, T B) {
      	(A>B)&&(A=B);//if(B<A)A=B;
      }
      template <class T>
      inline bool scan_d(T &ret) {
      	char c;
      	int sgn;
      	if(c=getchar(),c==EOF) return 0; //EOF
      	while(c!='-'&&(c<'0'||c>'9')) c=getchar();
      	sgn=(c=='-')?-1:1;
      	ret=(c=='-')?0:(c-'0');
      	while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
      	ret*=sgn;
      	return 1;
      }
      inline void outt(int x) {
      	if(x>9) outt(x/10);
      	putchar(x%10+'0');
      }
      const int maxn = 1e6+10;
      struct SegmentTree {
      	int l,r;
      	long long sum, add;
      #define l(x) tree[x].l
      #define r(x) tree[x].r
      #define sum(x) tree[x].sum
      #define add(x) tree[x].add
      } tree[1000010*4];
      int a[1000010],n,m;
      void build(int p,int l,int r) {
      	l(p)=l,r(p)=r;
      	add(p)=0;//注意初始化位置 
      	if(l==r) {
      		sum(p)=a[l];
      		return ;
      	}
      	int mid=(l+r)/2;//只有这里的一半是直接用传入的l,r,但实际上这里的l,r就是下面的p.l,p.r
      	build(p*2,l,mid);
      	build(p*2+1,mid+1,r);
      	sum(p)=sum(p*2)+sum(p*2+1);
      }
      //延迟标记代表:该节点已经被修改,但子节点尚未被更新
      void spread(int p) {
      	if(add(p)) {
      		sum(p*2) = add(p)*(r(p*2)-l(p*2)+1); //更新左子节点信息
      		sum(p*2+1) = add(p)*(r(p*2+1)-l(p*2+1)+1);//更新右子节点信息
      		add(p*2) = add(p); //给左子节点打延迟标记
      		add(p*2+1) = add(p);
      		add(p) = 0;//清楚p节点的标记
      	}
      }
      void change(int p,int l,int r,int d) {
      	if(l<=l(p) && r>=r(p)) { //完成覆盖
      		sum(p)=(long long)d*(r(p)-l(p)+1);//更新节点信息
      		add(p)=d;//给节点打延迟标记
      		return ;
      	}
      	spread(p); //下传延迟标记
      	int mid=(l(p)+r(p))/2; //这里的中间是当前节点的中间(或者说是偏左的中间)位置
      	if(l<=mid)change(p*2,l,r,d);
      	if(r>mid)change(p*2+1,l,r,d);//注意这里不是非此即彼的关系
      	sum(p)=sum(p*2)+sum(p*2+1);
      }
      long long ask(int p,int l,int r) {
      	if(l<=l(p) && r>=r(p))return sum(p);
      	spread(p);
      	int mid=(l(p)+r(p))/2;
      	long long val=0;
      	if(l <= mid) val+=ask(p*2,l,r);//注意!这里对中间元素进行比较的是l不是tree[p].l
      	if(r > mid) val+=ask(p*2+1,l,r);
      	return val;
      }
      char cmd[10];
      int main() {
      	int t;
      	cin>>t;
      	rep(l,1,t) {
      		int n,m;
      		scan_d(n),scan_d(m);
      		rep(i,1,n)a[i]=1;
      		build(1,1,n);
      		while(m--) {
      			int l,r,d;
      			scan_d(l);
      			scan_d(r);
      			scan_d(d);
      			change(1,l,r,d);
      		}
      		printf("Case %d: The total value of the hook is %d.\n",l,ask(1,1,n));
      	}
      	return 0;
      }
      

发表评论

邮箱地址不会被公开。 必填项已用*标注