lightoj 1089 【离散化+线段树】
题意:
给你n个区间,然后给你m个i点问你这个点在几个所给定的区间里;
思路:
给你n个区间,然后给你m个i点问你这个点在几个所给定的区间里;
思路:
离散化+区间覆盖
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int N=5e4+10; struct SegT{ int left,right; int val; int flag; }; SegT q[N*12]; int n,Q; int arr[N*4]; void Build(int num,int L,int R) { q[num].left=L; q[num].right=R; q[num].flag=q[num].val=0; if(L==R) return; int mid=(L+R)/2; Build(2*num, L,mid); Build(2*num+1,mid+1,R); } void Pushdown(int num) { if(q[num].flag) { q[2*num].val+=(q[2*num].right-q[2*num].left+1)*q[num].flag; q[2*num+1].val+=(q[2*num+1].right-q[2*num+1].left+1)*q[num].flag; q[2*num].flag+=q[num].flag; q[2*num+1].flag+=q[num].flag; q[num].flag=0; } } void Update(int num,int s,int t) { if(q[num].left>=s&&q[num].right<=t) { q[num].flag+=1; q[num].val+=(q[num].right-q[num].left+1); //wa在了这里。。只要加1就行了,无奈给乘了。。。q[num].flag...不过还是有长进/// return; } Pushdown(num); int mid=(q[num].left+q[num].right)/2; if(mid>=t) Update(2*num,s,t); else if(mid<s) Update(2*num+1,s,t); else { Update(2*num,s,mid); Update(2*num+1,mid+1,t); } q[num].val=q[2*num].val+q[2*num+1].val; } int query(int num,int id) { if(q[num].left==id&&q[num].left==q[num].right) return q[num].val; Pushdown(num); int mid=(q[num].right+q[num].left)/2; if(mid>=id) return query(2*num,id); else return query(2*num+1,id); } vector<int>xs; int main() { int T,cas=1; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&Q); xs.clear(); for(int i=1;i<=2*n;i+=2) { scanf("%d%d",&arr[i],&arr[i+1]); xs.push_back(arr[i]); xs.push_back(arr[i+1]); } for(int i=1;i<=Q;i++) { scanf("%d",&arr[i+2*n]); xs.push_back(arr[i+2*n]); } int num=0; sort(xs.begin(),xs.end()); vector<int>::iterator e=unique(xs.begin(),xs.end()); for(int i=1;i<=2*n+Q;i++) { arr[i]=lower_bound(xs.begin(),e,arr[i])-xs.begin()+1; num=max(num,arr[i]); } Build(1,1,num); for(int i=1;i<=2*n;i+=2) Update(1,arr[i],arr[i+1]); printf("Case %d:\n",cas++); for(int i=1;i<=Q;i++) printf("%d\n",query(1,arr[i+2*n])); } return 0; } /* 5 4 6 12 8 8 10 12 8 11 0 12 11 12 2 20 3 3 1 3 2 4 5 6 1 2 3 */