题意:
给出n个区间,【s,t】,区间,代表这个时间段有一朵花。
m个询问,每次询问一个时间点,输出该时间的花的数量。
思路:n <= 10W, m <= 10W 。
直接离散化之后然后线段树成段更新,输出点的值即可。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <stack>
#include <map>
#include <iomanip>
#define PI acos(-1.0)
#define Max 2005
#define inf 2000000000
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
#define REP(i,s,t) for(int i=(s);i<=(t);++i)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
#define mp(a,b) make_pair(a,b)
using namespace std;
struct kdq
{
int l,r;
long long num , add;
} tree[1111111];
int n , m , t ;
long long ans;
void build_tree(int l,int r,int u)
{
tree[u].l=l,tree[u].r=r;
tree[u].add=0;
if(l==r)
{
tree[u].num = 0 ;
return ;
}
int mid=(l+r)/2;
build_tree(l,mid,u<<1);
build_tree(mid+1,r,(u<<1)+1);
tree[u].num=tree[u<<1].num + tree[(u<<1)+1].num;
}
void query(int left,int right,int u)
{
if(left>tree[u].r||right<tree[u].l)
{
return ;
}
if(left<=tree[u].l&&right>=tree[u].r)
{
ans+=tree[u].num;
return ;
}
if(tree[u].add)
{
tree[u<<1].num += (tree[u<<1].r-tree[u<<1].l+1)*tree[u].add;
tree[u<<1].add += tree[u].add;
tree[(u<<1)+1].num += (tree[(u<<1)+1].r-tree[(u<<1)+1].l+1)*tree[u].add;
tree[(u<<1)+1].add += tree[u].add;
tree[u].add = 0;
}
query(left,right,u<<1);
query(left,right,(u<<1)+1);
tree[u].num=tree[u<<1].num+tree[(u<<1)+1].num;
}
void updata(int left,int right,int u,int k)
{
if(left>tree[u].r||right<tree[u].l)
{
return ;
}
if(left<=tree[u].l&&right>=tree[u].r)
{
tree[u].num+=(tree[u].r-tree[u].l+1)*k;
tree[u].add+=k;
return ;
}
if(tree[u].add)
{
tree[u<<1].num += (tree[u<<1].r-tree[u<<1].l+1)*tree[u].add;
tree[u<<1].add += tree[u].add;
tree[(u<<1)+1].num += (tree[(u<<1)+1].r-tree[(u<<1)+1].l+1)*tree[u].add;
tree[(u<<1)+1].add += tree[u].add;
tree[u].add = 0;
}
updata(left,right,u<<1,k);
updata(left,right,(u<<1)+1,k);
tree[u].num=tree[u<<1].num+tree[(u<<1)+1].num;
}
struct road
{
int x ,y ;
}a[100005] ;
int b[1000005] ;
int c[1000005] ;
int main()
{
#ifndef ONLINE_JUDGE
freopen("acm.txt", "r", stdin);
#endif
cin >> t ;
int ca = 0 ;
while( t -- )
{
cin >> n >> m ;
int dnum = 0 ;
for (int i = 0 ;i < n ;i ++ )
{
scanf("%d%d",&a[i].x ,&a[i].y) ;
b[dnum ++ ] = a[i].x ;
b[dnum ++ ] = a[i].y ;
}
for (int i = 0 ;i < m ;i ++ )
{
scanf("%d",&c[i]) ;
b[dnum ++ ] = c[i] ;
}
sort(b, b + dnum ) ;
int nn = unique(b,b + dnum) - b ;
build_tree(1,nn,1) ;
printf("Case #%d:\n",++ca) ;
for (int i = 0 ;i < n ;i ++ )
{
int ss = lower_bound(b,b + nn ,a[i].x) - b + 1 ;
int tt = lower_bound(b, b + nn ,a[i].y) - b + 1 ;
updata(ss, tt,1,1) ;
}
for (int i = 0 ;i < m ;i ++ )
{
ans = 0 ;
int dd = lower_bound(b, b + nn ,c[i]) - b + 1 ;
query(dd,dd,1) ;
printf("%lld\n",ans) ;
}
}
return 0;
}
显然用树状数组区间更新单点查询更快,更好写
int n , m ,nn ,D[N] ,X[N] , Y[N] ,Q[N] ,c[N] ;
int lowbit(int x){return x & (-x) ;}
void update(int x , int y){
for (int i = x ; i >= 1 ; i -= lowbit(i))c[i] += y ;
}
int query(int x){
int ans = 0 ;
for (int i = x ; i <= nn ; i += lowbit(i))ans += c[i] ;
return ans ;
}
void solve(){
mem(c , 0) ;
cin >> n >> m ;int num = 0 ;
for (int i = 0 ; i < n ; i ++ ){
RD(X[i]) ; RD(Y[i]) ;D[num ++ ] = X[i] ;
D[num ++ ] = Y[i] ;
}
for (int i = 0 ; i < m ; i ++ ){
RD(Q[i]) ; D[num ++ ] = Q[i] ;
}
sort(D , D + num) ;
int k = unique(D , D + num ) - D ;
nn = k ;
for (int i = 0 ; i < n ; i ++ ){
int x = lower_bound(D, D + k , X[i]) - D + 1 ;
int y = lower_bound(D ,D + k , Y[i]) - D + 1 ;
update(x - 1 , -1) ;
update(y , 1) ;
}
for (int i = 0 ; i < m ; i ++ ){
printf("%d\n",query(lower_bound(D, D + k , Q[i]) - D + 1)) ;
}
}
int main() {
int _ ;int ca = 0 ; cin >> _ ; while(_ -- )printf("Case #%d:\n",++ ca) ,solve() ;
return 0;
}