练习:线段树+扫描线
题意
一个序列,每次给一段区间一些数,询问每个点出现次数最多的数。
分析
扫描线,从左到右扫描,遇到区间的左端点,在权值线段树(下标是数字种类)中相应的位置+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 }