1. 程式人生 > >練習:線段樹+掃描線

練習:線段樹+掃描線

const pda || mes stdin 遇到 技術分享 update space

題意

一個序列,每次給一段區間一些數,詢問每個點出現次數最多的數。

分析

掃描線,從左到右掃描,遇到區間的左端點,在權值線段樹(下標是數字種類)中相應的位置+1,右端點-1。操作完成後,輸出權值線段樹中最大的(即出現次數)的數(下標)。

code

技術分享圖片
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<vector>
 4 #define lson l,m,rt<<1
 5 #define rson m+1,r,rt<<1|1
 6 
 7 using
namespace std; 8 const int N = 500100; 9 pair<int,int> mx[N]; 10 vector<int>vec[N]; 11 12 inline char nc() { 13 static char buf[100000],*p1,*p2; 14 return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; 15 } 16 inline int read() { 17 int x = 0,f = 1;char
ch = nc(); 18 for (; ch<0||ch>9; ch = nc()) if (ch==-) f=-1; 19 for (; ch>=0&&ch<=9; ch = nc()) x = x*10+ch-0; 20 return x * f; 21 } 22 void pushup(int rt) { 23 if (mx[rt<<1].first >= mx[rt<<1|1].first) mx[rt] = mx[rt<<1]; 24 else
mx[rt] = mx[rt<<1|1]; 25 } 26 void build(int l,int r,int rt) { 27 if (l == r) { 28 mx[rt] = make_pair(0,l);return ; 29 } 30 int m = (l + r) / 2; 31 build (lson); 32 build(rson); 33 pushup(rt); 34 } 35 void update(int l,int r,int rt,int p,int x) { 36 if (l == r) { 37 mx[rt].first += x;return ; 38 } 39 int m = (l + r) / 2; 40 if (p <= m) update(lson,p,x); 41 else update(rson,p,x); 42 pushup(rt); 43 } 44 int main () { 45 int n = read(),m = read(); 46 for (int i=1; i<=m; ++i) { 47 int a = read(),b = read(),c = read(); 48 vec[a].push_back(c),vec[b+1].push_back(-c); 49 } 50 build(1,100000,1); 51 for (int i=1; i<=n; ++i) { 52 int sz = vec[i].size(); 53 for (int j=0; j<sz; ++j) { 54 int v = vec[i][j]; 55 if (v>0) update(1,100000,1,v,1); 56 else update(1,100000,1,-v,-1); 57 } 58 if (mx[1].first==0) puts("-1"); 59 else printf("%d\n",mx[1].second); 60 } 61 return 0; 62 }
View Code

練習:線段樹+掃描線