校门外的树2 contest 树状数组练习 T4

Description

校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:K=1,读入l,r表示在区间[l,r]中种上一种树,每次操作种的树的种类都不同。K=2,读入l,r表示在区间[l,r]之间能见到多少种树(l,r>0)。


Input

第一行n,m,表示道路总长为n,共有m个操作。接下来m行,为m个操作。

Output

对于每个k=2输出一个答案。

Hint

对于20%的数据保证,n,m<=100。 对于60%的数据保证,n <=1000,m<=50000。 对于100%的数据保证,n,m<=50000。

Solution

用两个区间的树状数组分别维护起点数量和终点数量。那么查询的时候ans就等于r前面的起点数量减去l-1前面的终点数量。因为l-1前面就已经终点了的话,这种树就不包含在查询的这个区间里面。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define maxn 50005
#define lowbit(x) (x&(-x))
#define int long long
using namespace std;
int c1[maxn],c2[maxn],c3[maxn],c4[maxn];
int n,m,x,y,z;
void doAdd(int x,int dd){
    int f=x;
    while(x<=n){
        c1[x]+=f*dd;
        c3[x]+=dd;
        x+=lowbit(x);
    }
}
void doadd(int x,int dd){
    int f=x;
    while(x<=n){
        c2[x]+=f*dd;
        c4[x]+=dd;
        x+=lowbit(x);
    }
}
int doFinD(int x){
    int f=x,ans=0;
    while(x>0){
        ans+=(f+1)*c3[x]-c1[x];
        x-=lowbit(x);
    }
    return ans;
}
int dofinD(int x){
    int f=x,ans=0;
    while(x>0){
        ans+=(f+1)*c4[x]-c2[x];
        x-=lowbit(x);
    }
    return ans;
}
signed main(){
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%lld",&x);
        if(x==1){
            scanf("%lld%lld",&y,&z);
            doAdd(y,1);
            doAdd(y+1,-1);
            doadd(z,1);
            doadd(z+1,-1); 
        }
        else if(x==2){
            scanf("%lld%lld",&y,&z);
            printf("%lld\n",doFinD(z)-dofinD(y-1));
        }
    }
    return 0;
}

转载于:https://www.cnblogs.com/virtual-north-Illya/p/10045445.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值