练习:线段树+扫描线

题意

一个序列,每次给一段区间一些数,询问每个点出现次数最多的数。

分析

扫描线,从左到右扫描,遇到区间的左端点,在权值线段树(下标是数字种类)中相应的位置+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

 

posted @ 2018-02-09 21:30  MJT12044  阅读(149)  评论(0编辑  收藏  举报