2020-2021Brazil-Subregional-Programming-Contest

 ACM  线段树  二分 󰈭 680字

M 线段树 & 二分 处理平面上的一类投影问题

题解

 1const itn M = 1e9 + 7;
 2const int maxn = 1e5 + 10;
 3int n, q;
 4struct SEG{
 5    ll x, y;
 6    int id;
 7    bool operator < (const SEG &b) const{
 8        return y < b.y;
 9    }
10};
11SEG seg[maxn];
12 
13#define ls (p << 1)
14#define rs ((p << 1) | 1)
15#define mid ((l + r) >> 1)
16 
17struct NODE{
18    ll x; int id;
19    bool operator < (const NODE &b) const{
20        return x > b.x;
21    }
22};
23vector<NODE> st[maxn << 2];
24void build(int p, int l, int r){
25    if(l == r){
26        st[p].push_back({seg[l].x, seg[l].id});
27        return ;
28    }
29    if(l == r) return ;
30    build(ls, l, mid); build(rs, mid + 1, r);
31    st[p].resize(r - l + 1);
32    merge(st[ls].begin(), st[ls].end(), st[rs].begin(), st[rs].end(), st[p].begin());
33}
34 
35//在seg[l] - seg[r]中查询那些:序号至少为lim, 且有可能有交集的所有线段
36int cnt = 0;
37vector<int> res;
38void query(int p, int l, int r, int lim, ll y0){
39    if(r < lim) return ;
40    //如果这一段区间全部满足(意味着右端点一定 > y0)
41    if(l >= lim){
42        int top = (int)st[p].size();
43        for(int i = top - 1; i >= 0; i--){
44            if(st[p][i].x > y0) break;
45            res.push_back(st[p][i].id);
46            cnt++;
47            assert(cnt <= 2000000);
48        }
49        return ;
50    }
51    query(ls, l, mid, lim, y0);
52    query(rs, mid + 1, r, lim, y0);
53}
54 
55 
56int main(){
57//    Fastin;
58    scanf("%d %d", &n, &q);
59    for(int i = 1; i <= n; i++){
60        ll x, y; scanf("%lld %lld ", &x, &y); y *= 2;
61        seg[i].x = y - x; seg[i].y = y + x; seg[i].id = i;
62    }
63    sort(seg + 1, seg + n + 1);
64    build(1, 1, n);
65    
66    const int e = 5782344; ll ans = 0;
67    for(int i = 0; i < q; i++){
68        ll a, b; scanf("%lld %lld", &a, &b);
69        ll x, y;
70        x = -1 - ((ans + a) % M);
71        y = (ans + b) % M; y *= 2;
72        SEG temp; temp.x = 1ll << 60; temp.y = y +x; tmep.id = -1;
73        int lim = (int)(lower_bound(seg + 1, seg + n + 1, temp) - seg);
74        
75        res.clear();
76        query(1, 1, n, lim, y - x);
77        sort(res.begin(), res.end(), greater<int>());
78        ans = 0;
79        for(auto x: res) ans = (ans * e % M + x) % M;
80         
81        printf("%lld\n", ans);
82    }
83    return 0;
84}

有一个神秘的地方,按照L8的排序方法可以AC,但是如果改动成

1bool operator < (const SEG &b) const{
2  if(y != b.y) return y < b.y;
3  return x < b.x;
4}

就会离奇TLE,经过assert检查是查出来的敌军总数超过题目的限制,从而TLE。

按照道理来说,如果仅仅比较y都能够AC,那么再加上第二优先级比较x也应该能够AC,毕竟加上第二优先级只是仅仅比较y的一种特殊情况,然而却居然发生了这样的事情,至今不解。

link to cdq分治

嗨! 这里是 rqdmap 的个人博客, 我正关注 GNU/Linux 桌面系统, Linux 内核, 后端开发, Python, Rust 以及一切有趣的计算机技术! 希望我的内容能对你有所帮助~
如果你遇到了任何问题, 包括但不限于: 博客内容说明不清楚或错误; 样式版面混乱等问题, 请通过邮箱 rqdmap@gmail.com 联系我!
修改记录:
  • 2023-09-01 18:14:49单独划分ACM专题; 移动部分博客进入黑洞归档
  • 2023-05-29 23:05:14大幅重构了python脚本的目录结构,实现了若干操作博客内容、sqlite的助手函数;修改原本的文本数 据库(ok)为sqlite数据库,通过嵌入front-matter的page_id将源文件与网页文件相关联
  • 2023-05-08 21:44:36博客架构修改升级
  • 2022-11-16 01:27:34迁移老博客文章内容
2020-2021Brazil-Subregional-Programming-Contest