博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2018牛客多校第六场 I.Team Rocket
阅读量:4658 次
发布时间:2019-06-09

本文共 2725 字,大约阅读时间需要 9 分钟。

题意:

  给出n个区间和m个点(点按顺序给出且强制在线)。每个区间只会被第一个他包含的点摧毁。问每个点能摧毁多少个区间以及每个区间是被哪个点摧毁的。

题解:

  将n个区间按照左端点排序,然后用vector(储存左端点,右端点,id)初始化线段树。

  初始化的方法是:对于线段树的n个叶子节点,即为排好序的n个区间。对于其他节点,将左右儿子按照右端点大小归并(归并是线性复杂度)。

  还要维护每个节点左端点的最小值(用来剪枝)和最大值(用来判断可行性)。

  每个区间只会被第一个他包含的点摧毁,所以用vis数组标记一个区间是否已被摧毁。

  每次遍历vector数组后使用erase会T掉,可以再维护一个信息表示上次遍历到的位置,这次从这个位置开始遍历。

#include 
using namespace std;typedef long long ll;const int N = 2e5+10;const int mod = 998244353;int t, n, m;int x, y, lst, judge;int ans[N], vis[N];struct node { int l, r, id; bool operator < (const node &a) { return l == a.l ? r > a.r : l < a.l; }}a[N];int min_L[N<<2], max_L[N<<2], L[N<<2];vector
g[N<<2]; void merge(int id) { int lch = id<<1, rch = id<<1|1; max_L[id] = max(max_L[lch], max_L[rch]); min_L[id] = min(min_L[lch], min_L[rch]); int len1 = g[lch].size(), len2 = g[rch].size(); int l1 = 0, l2 = 0; while(l1 < len1 || l2 < len2) { if(l1 == len1 || l2 != len2 && g[rch][l2].r > g[lch][l1].r) g[id].push_back(g[rch][l2++]); else g[id].push_back(g[lch][l1++]); }}void build(int id, int l, int r) { g[id].clear(); L[id] = 0; if(l == r) { g[id].push_back(a[l]); max_L[id] = min_L[id] = a[l].l; return ; } int mid = l+r >> 1; build(id<<1, l, mid); build(id<<1|1, mid+1, r); merge(id);}int query(int id, int l, int r, int ql, int num) { if(min_L[id] > ql) return 0; if(max_L[id] <= ql) { int cnt = L[id], tot = 0; int len = g[id].size(); while(cnt < len && g[id][cnt].r >= ql) { int v = g[id][cnt].id; if(!vis[v]) { lst = 1ll*lst*v%mod; judge++; ans[v] = num; vis[v] = 1; tot++; } cnt++; } L[id] = cnt; return tot; } int res = 0; int mid = l+r>>1; res += query(id<<1, l, mid, ql, num); res += query(id<<1|1, mid+1, r, ql, num); return res;}int main() { scanf("%d", &t); for(int casee = 1; casee <= t; casee++) { printf("Case #%d:\n", casee); scanf("%d%d", &n, &m); for(int i = 1; i <= n; i++) { scanf("%d%d", &a[i].l, &a[i].r); ans[i] = vis[i] = 0; a[i].id = i; } sort(a+1, a+n+1); build(1, 1, n); lst = 0; for(int i = 1; i <= m; i++) { scanf("%d", &y); x = y^(lst % mod); lst = 1, judge = 0; printf("%d\n", query(1, 1, n, x, i)); if(!judge) lst = 0; } for(int i = 1; i < n; i++) printf("%d ", ans[i]); printf("%d\n", ans[n]); }}
View Code

 

转载于:https://www.cnblogs.com/Pneuis/p/9425413.html

你可能感兴趣的文章
dll和exe的共享节------多进程共享dll/exe全局变量
查看>>
Flex编程注意之如何得到itemRenderer里面的内容
查看>>
最近的一点思考,关于高手/大师/学霸
查看>>
css要点
查看>>
UIActivityIndicatorView
查看>>
大数据学习系列(5)-- 局域网yum仓库搭建
查看>>
[Canvas]新版箴言钟表
查看>>
杭电(hdu)2053 Switch Game 水题
查看>>
SDUT -refresh的停车场(栈和队列)
查看>>
使用Charles请求跳转可作为线上和线下环境的切换
查看>>
跨域请求
查看>>
浅谈Java反射
查看>>
cocos2d-x 3.8 lua 关于setAnimationCompletedCallback的修改
查看>>
mongo
查看>>
BZOJ 2037 区间DP
查看>>
hihocoder1415 重复旋律3
查看>>
STL-queue和循环队列基本操作的实现
查看>>
Python 字符串常用方法
查看>>
ant中build.xml文件解释
查看>>
自动化测试
查看>>