题目链接:CSU 2170
题目大意:对[1,n]的区间进行q次操作.有下面2种类型
- 1:添加一条[l,r]的线段
- 2:查询可以完全覆盖[l,r]区间的线段有多少条
需要注意的是查询区间 r-l<=2
分析:
这么一个水题之前和队友想了一天都没想出来.今天又看了这道题,才发现还有个查询区间 r-l<=2 的条件. emmm,没漏看条件的话这题还是很好写的.维护下区间内左右端点的个数,减下就能出来了. r-l==2 的话加上重复减的就是答案了.
以下是代码:
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#define Fi first
#define Se second
#define ll long long
#define inf 0x3f3f3f3f
#define lowbit(x) (x&-x)
#define PLL pair<ll,ll>
#define PII pair<int,int>
#define in(b) scanf("%d",&b)
#define l_inf 0x3f3f3f3f3f3f3f
#define mmin(a,b,c) min(a,min(b,c))
#define mmax(a,b,c) max(a,max(b,c))
#define debug(a) cout<<#a<<"="<<a<<endl;
#define debug2(a,b) cout<<#a<<"="<<a<<" "<<#b<<"="<<b<<endl;
using namespace std;
const int N=1e5+10;
int cnt[N],s1[N<<2],s2[N<<2];
void update(int l,int r,int p,int k,int tr[])
{
if(l==r)
{
tr[k]++;
return ;
}
int m=(l+r)>>1;
if(p<=m) update(l,m,p,k<<1,tr);
else update(m+1,r,p,k<<1|1,tr);
tr[k]=tr[k<<1]+tr[k<<1|1];
}
int query(int l,int r,int L,int R,int k,int tr[])
{
if(l>=L&&r<=R)
{
return tr[k];
}
if(l==r) return 0;
int m=(l+r)>>1;
int ans=0;
if(L<=m) ans+=query(l,m,L,R,k<<1,tr);
if(R>m) ans+=query(m+1,r,L,R,k<<1|1,tr);
return ans;
}
int main()
{
int n,q;
while(~scanf("%d%d",&n,&q))
{
int sta,l,r,ss=0;
memset(s1,0,sizeof s1);
memset(s2,0,sizeof s2);
memset(cnt,0,sizeof cnt);
while(q--)
{
scanf("%d%d%d",&sta,&l,&r);
if(sta==1)
{
ss++;
if(l==r) cnt[l]+=2;
update(1,n,l,1,s1);
update(1,n,r,1,s2);
}
else
{
int l1,r1,l2,r2;
l1=1;r1=r-1;
l2=l+1;r2=n;
int ans=ss;
if(l1<=r1) ans-=query(1,n,l1,r1,1,s2);
if(l2<=r2) ans-=query(1,n,l2,r2,1,s1);
if(r-l==2) ans+=cnt[l+1];
printf("%d\n",ans);
}
}
}
return 0;
}
/*
4 3
1 1 4
1 3 3
2 2 4
*/