CodeForces - 652D Nested Segments(線段樹/樹狀陣列+離散化)
阿新 • • 發佈:2018-11-10
看了大佬的部落格:https://blog.csdn.net/chenquanwei_/article/details/79137969;
題意:給n個線段的左右端點,問每個線段包括多少線段;類似於https://blog.csdn.net/weixin_42754600/article/details/81914015;
把左右端點看成x,y座標,先離散化一下,然後按照x降序,x相等y升序排列一下,計算每個點前面有多少個y座標小於等於它就行了;
離散化就是把資料範圍變小,但是不改變相對大小,比如(-1e9,0,1e9) 離散化以後是(1,2,3) ; 計算起來方便
線段樹;
#include<cstdio> #include<iostream> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 2e5+10; int a[maxn],t[maxn<<2],y; struct node{ int x,y,s,t;//x,y是左右區間,s是輸入的順序,t是包含多少線段 }no[maxn]; bool cmp1(node a,node b){ return a.x>b.x||(a.x==b.x&&a.y<b.y); } bool cmp2(node a,node b){ return a.s<b.s; } int query(int l,int r,int rt){ int ans = 0; if(r <= y) ans+=t[rt]; else if(y < l) return 0; else{ int mid = (l+r)>>1; ans += query(l,mid,rt<<1); ans += query(mid+1,r,rt<<1|1); } return ans; } void update(int l,int r,int rt){ if(l == r){ t[rt]++; return; } int mid = (l+r)>>1; if(y<=mid) update(l,mid,rt<<1); else update(mid+1,r,rt<<1|1); t[rt]++; } int main() { int n; while(cin>>n){ int k = n; memset(no,0,sizeof(no)); memset(a,0,sizeof(a)); memset(t,0,sizeof(t)); for(int i = 0;i < k;i++){ cin>>no[i].x>>a[i]; no[i].y = a[i]; no[i].s = i; } sort(a, a + n); n = unique(a, a + n) - a; for(int i = 0; i < k; i++) no[i].y = lower_bound(a, a + n, no[i].y) - a+1;//離散化,加一是不要零,從一開始 sort(no,no+n,cmp1); for(int i = 0; i < k; i++){ y = no[i].y; no[i].t = query(0,maxn,1);//查詢 update(0,maxn,1);//更新 } sort(no,no+n,cmp2); for(int i = 0; i < k; i++) cout<<no[i].t<<endl; } return 0; }
樹狀陣列:
#include<cstdio> #include<iostream> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int maxn = 2e5+10; int a[maxn],t[maxn],y; struct node{ int x,y,s,t;//x,y是左右區間,s是輸入順序,t是包含多少區間 }no[maxn]; bool cmp1(node a,node b){ return a.x>b.x||(a.x==b.x&&a.y<b.y); } bool cmp2(node a,node b){ return a.s<b.s; } int lowbit(int x){ return x&(-x); } int query(int x){ int ans = 0; while(x){ ans += t[x]; x -= lowbit(x); } return ans; } void update(int x){ while(x<=maxn){ t[x]++; x += lowbit(x); } return; } int main() { int n; while(cin>>n){ int k = n; memset(no,0,sizeof(no)); memset(a,0,sizeof(a)); memset(t,0,sizeof(t)); for(int i = 0;i < k;i++){ cin>>no[i].x>>a[i]; no[i].y = a[i]; no[i].s = i; } sort(a, a + n); n = unique(a, a + n) - a; for(int i = 0; i < k; i++) no[i].y = lower_bound(a, a + n, no[i].y) - a+1;//離散化,加一是不要零,從一開始 sort(no,no+n,cmp1); for(int i = 0; i < k; i++){ y = no[i].y; no[i].t = query(y);//查詢 update(y);//更新 } sort(no,no+n,cmp2); for(int i = 0; i < k; i++) cout<<no[i].t<<endl; } return 0; }