CF 609F,线段树上二分 + set维护

(。・∀・)ノ゙嗨大家好,sb我又回来切题了(因为不切大概就要弱死了)

题目大意:在数轴上给定n只青蛙,每只青蛙有一个舌头长度,每只青蛙能吃落在他右边不超过舌头长的蚊子,吃了蚊子蛇头能长长,多只青蛙能吃到则取最左边的一只。

解:原来我的想法是线段树维护区间最小值然后set维护一下看舌头伸长后能吃哪些蚊子。但是由于距离需要离散化,所以导致这个做法细节会非常爆炸。看了一下题解,非常巧妙,维护区间青蛙长度伸到的最右的位置,然后直接在线段树上二分,因为如果左右一块可以覆盖到当前蚊子,肯定是走左边,不然查询右边。

有个trick(其实是我自己傻逼了),如果set里面放的是二元组,但是小于重载只判了一个,那么第二个元不一样的东西也会看作一样,不开multiset就会因为重复插不进去,另外这里记载一个上次周赛的sb错误,就是multiset如果erase(构造函数)的话,不是删除第一个该结构,而是相同的全部删掉,因此如果想删掉第一个的话,用返回迭代器的lower_bound或者find才行。

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <utility>
  5 #include <map>
  6 #include <string>
  7 #include <cmath>
  8 #include <vector>
  9 #include <cstring>
 10 #include <stack>
 11 #include <set>
 12 #include <queue>
 13 
 14 using namespace std;
 15 
 16 #define SQR(x) ((x)*(x))
 17 #define LL long long
 18 #define LOWBIT(x) ((x)&(-(x)))
 19 #define PB push_back
 20 #define MP make_pair
 21 #define SQR(x) ((x)*(x))
 22 #define LSON(x) ((x)<<1)
 23 #define RSON(x) (((x)<<1)+1)
 24 
 25 
 26 #define MAXN 211111
 27 
 28 const double EPS = 1e-6;
 29 
 30 struct data{
 31     int p, sz;
 32     data(int a = 0, int b = 0): p(a), sz(b) {}
 33     bool operator < (const data &rhs) const {
 34         return p > rhs.p;
 35     }
 36 };
 37 
 38 vector <pair<int, pair<int, int > > > a;
 39 multiset <data > s;
 40 int cnt[MAXN], stp[MAXN];
 41 int n, m;
 42 LL ans[MAXN], ans2[MAXN];
 43 
 44 LL len[MAXN];
 45 
 46 struct SegTree{
 47     LL maxx[MAXN*4];
 48     int l[MAXN*4], r[MAXN*4], m[MAXN*4];
 49     int gx, gy;
 50     LL gz;
 51     inline void setting(int aa = 0, int bb = 0, LL cc = 0) {
 52         gx = aa; gy = bb; gz = cc;
 53     }
 54     void updata(const int &kok) {
 55         if (l[kok] == r[kok]) ;
 56         else {
 57             maxx[kok] = max(maxx[kok], maxx[LSON(kok)]);
 58             maxx[kok] = max(maxx[kok], maxx[RSON(kok)]);
 59         }
 60     }
 61     void build(int kok, int ll, int rr) {
 62         l[kok] = ll; r[kok] = rr;
 63         if (ll == rr) {
 64             maxx[kok] = len[ll];
 65             return ;
 66         }
 67         m[kok] = (ll + rr) >> 1;
 68         build(LSON(kok), ll, m[kok]);
 69         build(RSON(kok), m[kok] + 1, rr);
 70         updata(kok);
 71     }
 72     void insert(int kok = 1) {
 73         if (l[kok] == r[kok]) {
 74             maxx[kok] = gz;
 75             return ;
 76         }
 77         if (gx <= m[kok]) insert(LSON(kok));
 78         else insert(RSON(kok));
 79         updata(kok);
 80     }
 81     int query(int kok = 1) {
 82         if (maxx[kok] < gz) return -1;
 83         if (stp[l[kok]] > gz) return -1;
 84         if (l[kok] == r[kok]) {
 85             return l[kok];
 86         }
 87         if (maxx[LSON(kok)] >= gz) return query(LSON(kok));
 88         return query(RSON(kok));
 89     }
 90 } ST;
 91 
 92 void init() {
 93     cin >> n >> m;
 94     int x, y;
 95     a.PB(MP(-1, MP(-1, -1)));
 96     for (int i = 1; i <= n; ++i) {
 97         cin >> x >> y;
 98         a.PB(MP(x, MP(y, i)));
 99     }
100     sort(a.begin() + 1, a.end());
101     memset(cnt, 0, sizeof(cnt[0])*(n+10));
102     for (int i = 1; i <= n; ++i) {
103         stp[i] = a[i].first;
104         len[i] = a[i].first + a[i].second.first; 
105     }
106     ST.build(1, 1, n);
107 }
108 
109 void solve() {
110     s.clear();
111     set <data >::iterator it;
112     int p, sz;
113     int t;
114     while (m -- ){
115         cin >> p >> sz;
116         ST.setting(0, 0, p);
117         t = ST.query();
118         
119 //        cout << p <<' ' << sz <<' '<< t << endl;
120         if (t == -1) s.insert(data(p, sz));
121         else {
122         //    cout << len[t] << endl;
123 //            if (t == 5) cout << p <<' '<< sz <<endl;
124             len[t] += sz;
125             ++cnt[t];
126         //    cout << len[t] << endl;
127             while (s.size()) {
128                 it = s.lower_bound(len[t]);
129                 if (it == s.end()) break;
130         //        cout << "==============" << endl;
131         //        cout << t << ' '<< (*it).p << ' '<< stp[t] << endl;
132                 if ((*it).p < stp[t]) break;
133                 while (it != s.end()) {
134                     if ((*it).p >= stp[t]) {
135                         if (t == 5) {
136 //                            cout << (*it).p << ' '<< (*it).sz << endl;
137                         }
138                         len[t] += (*it).sz;
139                         ++cnt[t];
140                     }
141                     else break;
142                     s.erase(it++);
143                 }
144             }
145             ST.setting(t, 0, len[t]);
146             ST.insert();
147         //    cout << len[t] << endl;
148         }
149         
150     }
151 }
152 
153 void print() {
154     for (int i = 1; i <= n; ++i) {
155         ans[a[i].second.second] = len[i] - stp[i]; 
156         ans2[a[i].second.second] = cnt[i];
157     }
158     for (int i = 1; i <= n; ++i) {
159         cout << ans2[i] << ' '<< ans[i] << endl;
160     }
161 }
162 
163 int main() {
164 //    freopen("test.txt", "r", stdin);
165 //    freopen("my.txt", "w", stdout );
166     ios::sync_with_stdio(false);
167     init();
168     solve();
169     print();
170     return 0;
171 }
CF 609F
原文地址:https://www.cnblogs.com/wmzisfoolish/p/5898049.html