题意:看到题意和配图,我也是醉了。。。DotA屠夫的钩,是一节一节组成的,有n节,初始每节的长度是1。屠夫可以改变一个区间内每节的长度为1,2,3。。。问q次改变以后,总长度是多少。
思路:线段树(区间更新)。区间保存的是对应钩子区间每节的长度,如果区间内长度不一,则这个区间是无效的,需要考察这个区间的子区间,直到有一个统一的长度。
#include <iostream> #include <stdio.h> #include <cmath> #include <algorithm> #include <iomanip> #include <cstdlib> #include <string> #include <vector> #include <queue> #include <stack> #include <map> #include <set> #include <ctype.h> using namespace std; struct node{ int l; int r; int val; bool flag; }; node tree[400010]; void build_tree(int n,int l,int r){ tree[n].l=l; tree[n].r=r; tree[n].val=1; tree[n].flag=1; if(l==r)return; int mid=(l+r)/2; build_tree(n*2,l,mid); build_tree(n*2+1,mid+1,r); } void update(int n,int l,int r,int v){ if(tree[n].l==l&&tree[n].r==r){ tree[n].val=v; tree[n].flag=1; return;//应用了lazy思想,暂时不更新子区间。 } int mid=(tree[n].l+tree[n].r)/2; if(tree[n].flag){//这个时候不得不更新子区间了。 update(n*2,tree[n].l,mid,tree[n].val); update(n*2+1,mid+1,tree[n].r,tree[n].val); } if(r<=mid){ update(n*2,l,r,v); }else{ if(l<=mid){//跨区间 update(n*2,l,mid,v); update(n*2+1,mid+1,r,v); }else{ update(n*2+1,l,r,v); } } tree[n].flag=0; } int sum(int n){ if(tree[n].flag||(tree[n].l==tree[n].r)){ int tmp=tree[n].val; return (tree[n].r-tree[n].l+1)*tree[n].val; } return sum(n*2)+sum(n*2+1); } int main(){ int t; cin>>t; int cas=0; while(t--){ cas++; int n,q; cin>>n>>q; build_tree(1,1,n); while(q--){ int a,b,c; scanf("%d%d%d",&a,&b,&c); update(1,a,b,c); } printf("Case %d: The total value of the hook is %d.\n",cas,sum(1)); } return 0; }