Evanyou Blog 彩带

Vijos1448 校门外的树 [树状数组]

  题目传送门

校门外的树

描述

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

格式

输入格式

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

输出格式

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

样例1

样例输入1

5 4
1 1 3
2 2 5
1 2 4
2 3 5

样例输出1

1
2

限制

1s

提示

范围:20%的数据保证,n,m<=100
60%的数据保证,n <=1000,m<=50000
100%的数据保证,n,m<=50000

来源

dejiyu@CSC WorkGroup

 


  分析:

  最大区间覆盖的模板题。

  如果是区间修改和单点查询,那么我们在修改的时候只要$update(l,1),update(r+1,-1)$就行了,也就是说先从$l$开始$+1$,再从$r+1$开始$-1$,也就保证了只有$[l,r]$被修改。但这题是区间修改与区间查询,因此我们采用开两个树状数组的方法,一个记录$l$的修改,一个记录$r$的修改。

  Code:

 

//It is made by HolseLee on 3rd Sep 2018
//Vijos 1448
#include<bits/stdc++.h>
using namespace std;

const int N=5e4+7;
int n,m,c[N],b[N];

inline int read()
{
    char ch=getchar(); int num=0; bool flag=false;
    while( ch<'0' || ch>'9' ) {
        if( ch=='-' ) flag=true;
        ch=getchar();
    }
    while( ch>='0' && ch<='9' ) {
        num=num*10+ch-'0';
        ch=getchar();
    }
    return flag ? -num : num;
}

inline int lowbit(int x)
{
    return x&(-x);
}

inline void update1(int x) 
{
    for(; x<=n; x+=lowbit(x)) c[x]++;
}

inline void update2(int x)
{
    for(; x<=n; x+=lowbit(x)) b[x]++;
}

inline int quary1(int x)
{
    int ret=0;
    for(; x>0; x-=lowbit(x)) ret+=c[x];
    return ret;
}

inline int quary2(int x)
{
    int ret=0;
    for(; x>0; x-=lowbit(x)) ret+=b[x];
    return ret;
}

int main()
{
    n=read(); m=read();
    int opt,x,y;
    for(int i=1; i<=m; ++i) {
        opt=read(), x=read() ,y=read();
        if( opt==1 ) {
            update1(x); update2(y);
        } else {
            printf("%d\n",quary1(y)-quary2(x-1));
        }
    }
    return 0;
}

 

posted @ 2018-09-03 17:12  HolseLee  阅读(351)  评论(0编辑  收藏  举报