描述
校门外有很多树,有苹果树,香蕉树,有会扔石头的,有可以吃掉补充体力的……
如今学校决定在某个时刻在某一段种上一种树,保证任一时刻不会出现两段相同种类的树,现有两个操作:
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
输出
1
2
备注
范围:20%的数据保证,n,m<=100
60%的数据保证,n <=1000,m<=50000
100%的数据保证,n,m<=50000
注意:树是可以重叠的,比如1号位置上可以种多种树
题解
用两个线段树维护每个节点左右端点个数,端点数即是该点上覆盖的线段;
代码
1 #include <cstdio> 2 #include <cmath> 3 #include <cstring> 4 #include <ctime> 5 #include <iostream> 6 #include <algorithm> 7 #include <set> 8 #include <vector> 9 #include <queue> 10 #include <typeinfo> 11 #include <map> 12 #include <stack> 13 typedef long long ll; 14 #define inf 0x7fffffff 15 using namespace std; 16 inline ll read() 17 { 18 ll x=0,f=1; 19 char ch=getchar(); 20 while(ch<‘0‘||ch>‘9‘) 21 { 22 if(ch==‘-‘)f=-1; 23 ch=getchar(); 24 } 25 while(ch>=‘0‘&&ch<=‘9‘) 26 { 27 x=x*10+ch-‘0‘; 28 ch=getchar(); 29 } 30 return x*f; 31 } 32 //************************************************************************************** 33 int n,m; 34 struct ss 35 { 36 int l,r; 37 int left,right; 38 } tr[200001]; 39 void build(int k,int s,int t) 40 { 41 tr[k].left=s; 42 tr[k].right=t; 43 if(s==t)return; 44 int mid=(s+t)>>1; 45 build(k<<1,s,mid); 46 build(k<<1|1,mid+1,t); 47 } 48 void insertl(int k,int x,int y) 49 { 50 int l=tr[k].left,r=tr[k].right; 51 if(l==x&&y==r) 52 { 53 tr[k].l++; 54 return; 55 } 56 int mid=(l+r)>>1; 57 if(y<=mid)insertl(k<<1,x,y); 58 else if(x>mid)insertl(k<<1|1,x,y); 59 else 60 { 61 insertl(k<<1,x,mid); 62 insertl(k<<1|1,mid+1,y); 63 } 64 } 65 void insertr(int k,int x,int y) 66 { 67 int l=tr[k].left,r=tr[k].right; 68 if(l==x&&y==r) 69 { 70 tr[k].r++; 71 return; 72 } 73 int mid=(l+r)>>1; 74 if(y<=mid)insertr(k<<1,x,y); 75 else if(x>mid)insertr(k<<1|1,x,y); 76 else 77 { 78 insertr(k<<1,x,mid); 79 insertr(k<<1|1,mid+1,y); 80 } 81 } 82 int askl(int k,int x) 83 { 84 int l=tr[k].left,r=tr[k].right; 85 if(l==r)return tr[k].l; 86 int mid=(l+r)>>1; 87 if(x<=mid)return tr[k].l+askl(k<<1,x); 88 else return tr[k].l+askl(k<<1|1,x); 89 } 90 int askr(int k,int x) 91 { 92 int l=tr[k].left,r=tr[k].right; 93 if(l==r)return tr[k].r; 94 int mid=(l+r)>>1; 95 if(x<=mid)return tr[k].r+askr(k<<1,x); 96 else return tr[k].r+askr(k<<1|1,x); 97 } 98 int main() 99 { 100 int total=0,ans; 101 scanf("%d%d",&n,&m); 102 build(1,0,n);//l最小为1,所以是0到n 103 for(int i=1; i<=m; i++) 104 { 105 int t,a,b; 106 scanf("%d%d%d",&t,&a,&b); 107 if(t==1) 108 { 109 insertl(1,0,a-1);//考虑到a==1 110 insertr(1,b+1,n); 111 total++; 112 } 113 else 114 { 115 ans=askr(1,a)+askl(1,b); 116 printf("%d\n",total-ans); 117 } 118 } 119 return 0; 120 }
时间: 2024-10-14 12:30:43