校门外的树
链接
题目大意
现有一排格子,可以进行两种操作: k = 1 k=1 k=1时,在 [ l , r ] [l,r] [l,r]的每个格子中放置一个数 x x x; k = 2 k=2 k=2时,读取 [ l , r ] [l,r] [l,r]的每个格子中不同数的种类。
Input
第一行n,m表示道路总长为n,共有m个操作
接下来m行为m个操作
Output
对于每个k=2输出一个答案
Sample Input
5 4
1 1 3
2 2 5
1 2 4
2 3 5
Sample Output
1
2
思路
- 这题应该是之前用DP做过的。
- 这里要用到两个一维数组。一个用来存种树区间的左端点,另一个用来存右端点。
- 对于每个询问,先统计坐标为(0,r]的左端点的个数,表示(0,r]一共种了多少种数,再统计坐标为(0,l)的右端点的个数,表示右多少种树完全重在l的左边。最后再把两个值相减即为询问的答案。
代码
#include<algorithm>
#include<cstdio>
using namespace std;
int n,m,k,l,r,a[2][50001],c1,c2;
int lb(int i)
{
return i&(-i);
}
void add(int i,int t)
{
while(i<=n)
{
a[t][i]++;
i+=lb(i);
}
}
int cou(int i,int t)
{
int ans=0;
while(i>0)
{
ans+=a[t][i];
i-=lb(i);
}
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&k,&l,&r);
if(k==1)
{
add(l,0);//在l插入一个“左端点”
add(r,1);//在r插入一个“右端点
}
if(k==2)
{
c1=cou(r,0);//统计r左边的“左端点”的个数
c2=cou(l-1,1);//统计l-1左边的“右端点”的个数
printf("%d\n",c1-c2);
}
}
return 0;
}