【Tyvj】1473校门外的树3 线段树/树状数组 <区间修改+单点访问>

描述

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

输入格式

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

输出格式

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

测试样例1

输入

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

输出


2

备注

范围:20%的数据保证,n,m<=100
      60%的数据保证,n <=1000,m<=50000
      100%的数据保证,n,m<=50000
注意:树是可以重叠的,比如1号位置上可以种多种树

题解

用两个线段树维护每个节点左右端点个数,端点数即是该点上覆盖的线段;

代码

 #include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <queue>
#include <typeinfo>
#include <map>
#include <stack>
typedef long long ll;
#define inf 0x7fffffff
using namespace std;
inline ll read()
{
ll x=,f=;
char ch=getchar();
while(ch<''||ch>'')
{
if(ch=='-')f=-;
ch=getchar();
}
while(ch>=''&&ch<='')
{
x=x*+ch-'';
ch=getchar();
}
return x*f;
}
//**************************************************************************************
int n,m;
struct ss
{
int l,r;
int left,right;
} tr[];
void build(int k,int s,int t)
{
tr[k].left=s;
tr[k].right=t;
if(s==t)return;
int mid=(s+t)>>;
build(k<<,s,mid);
build(k<<|,mid+,t);
}
void insertl(int k,int x,int y)
{
int l=tr[k].left,r=tr[k].right;
if(l==x&&y==r)
{
tr[k].l++;
return;
}
int mid=(l+r)>>;
if(y<=mid)insertl(k<<,x,y);
else if(x>mid)insertl(k<<|,x,y);
else
{
insertl(k<<,x,mid);
insertl(k<<|,mid+,y);
}
}
void insertr(int k,int x,int y)
{
int l=tr[k].left,r=tr[k].right;
if(l==x&&y==r)
{
tr[k].r++;
return;
}
int mid=(l+r)>>;
if(y<=mid)insertr(k<<,x,y);
else if(x>mid)insertr(k<<|,x,y);
else
{
insertr(k<<,x,mid);
insertr(k<<|,mid+,y);
}
}
int askl(int k,int x)
{
int l=tr[k].left,r=tr[k].right;
if(l==r)return tr[k].l;
int mid=(l+r)>>;
if(x<=mid)return tr[k].l+askl(k<<,x);
else return tr[k].l+askl(k<<|,x);
}
int askr(int k,int x)
{
int l=tr[k].left,r=tr[k].right;
if(l==r)return tr[k].r;
int mid=(l+r)>>;
if(x<=mid)return tr[k].r+askr(k<<,x);
else return tr[k].r+askr(k<<|,x);
}
int main()
{
int total=,ans;
scanf("%d%d",&n,&m);
build(,,n);//l最小为1,所以是0到n
for(int i=; i<=m; i++)
{
int t,a,b;
scanf("%d%d%d",&t,&a,&b);
if(t==)
{
insertl(,,a-);//考虑到a==1
insertr(,b+,n);
total++;
}
else
{
ans=askr(,a)+askl(,b);
printf("%d\n",total-ans);
}
}
return ;
}
上一篇:MySQL单表SELECT查询ORDER BY导致FILESORT


下一篇:mysql-复杂的sql分组和排序