洛谷 1276 校门外的树(增强版)
【题解】
用线段树维护即可。区间设为一个数以及询问区间的和。第二问的答案可以用砍掉的树的总数减去砍树区间覆盖的范围。
1 #include<cstdio> 2 #include<algorithm> 3 #define N 200010 4 #define rg register 5 #define ls (u<<1) 6 #define rs (u<<1|1) 7 using namespace std; 8 int n,m,cnt,tot,s[N],ans; 9 struct tree{ 10 int l,r,sum,set,num; 11 }a[N]; 12 inline int read(){ 13 int k=0,f=1; char c=getchar(); 14 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 15 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 16 return k*f; 17 } 18 inline void pushdown(int u){ 19 if(!a[u].set) return; 20 a[ls].set=a[rs].set=1; 21 a[ls].num=a[rs].num=a[u].num; 22 a[ls].sum=a[u].num*(a[ls].r-a[ls].l+1); 23 a[rs].sum=a[u].num*(a[rs].r-a[rs].l+1); 24 a[u].set=0; 25 } 26 void build(int u,int l,int r){ 27 a[u].l=l; a[u].r=r; 28 if(l<r){ 29 int mid=(l+r)>>1; 30 build(ls,l,mid); build(rs,mid+1,r); 31 a[u].sum=a[ls].sum+a[rs].sum; 32 } 33 else a[u].sum=1; 34 } 35 void update(int u,int l,int r,int s){ 36 if(l<=a[u].l&&a[u].r<=r){ 37 a[u].set=1; a[u].num=s; a[u].sum=s*(a[u].r-a[u].l+1); 38 return; 39 } 40 pushdown(u); int mid=(a[u].l+a[u].r)>>1; 41 if(l<=mid) update(ls,l,r,s); 42 if(r>mid) update(rs,l,r,s); 43 a[u].sum=a[ls].sum+a[rs].sum; 44 } 45 int query(int u,int l,int r){ 46 if(l<=a[u].l&&a[u].r<=r) return a[u].sum; 47 pushdown(u); int mid=(a[u].l+a[u].r)>>1,ret=0; 48 if(l<=mid) ret+=query(ls,l,r); 49 if(r>mid) ret+=query(rs,l,r); 50 return ret; 51 } 52 int main(){ 53 n=read(); m=read(); build(1,0,n); 54 for(rg int i=1;i<=m;i++){ 55 int opt=read(),l=read(),r=read(); 56 if(!opt) cnt+=query(1,l,r),update(1,l,r,0),s[l]++,s[r+1]--; 57 else update(1,l,r,1); 58 } 59 if(s[0]) tot++,ans+=query(1,1,1); 60 for(rg int i=1;i<=n;i++){ 61 s[i]+=s[i-1]; 62 if(s[i]>0) tot++,ans+=query(1,i,i); 63 } 64 printf("%d\n",ans); 65 printf("%d\n",cnt-tot); 66 return 0; 67 }