SMOJ 2202 怪物 (整体二分+BIT)
题目描述
输入格式
第一行为数据组数。
对于每一组数据:
输出格式
对于每一组数据:
共N行,第i行输出一个整数,表示第i个团队最早是在哪一轮攻击后就解散,或者-1.
输入样例
1
3 5
1 3 2 1 3
10 5 7
3
4 2 4
1 3 1
3 5 2
输出样例
3
-1
1
题解
这题是整体二分的果题,本来没有什么好讲的,但是蒟蒻我还是打算水一篇博客。。。(因为ACM我们队大半个上午都在码这题,还码不对这题还是有一些值得总结的地方的)
这题与动态区间第K大是有区别的,区别在于修改操作不用放进队列了。这是为什么呢?因为我们二分轮数就可以直接知道该进行哪一段操作了,所以没有放进队列里的必要了?这并不是本质的区别。因为我们动态区间第K大里也可以先将询问排序然后整体二分中再二分找到修改的上下界并完成修改。(很有道理)
你说等等?排序?发现问题了,由于我们要保证询问与修改的相对顺序,所以哪能排序啊!这才是本质的区别。本题题目并没有修改、查询的交替给出,所以并不需要将修改当做操作,放进队列中保证相对顺序地排序,而是直接根据二分出来的轮数进行攻击就可以了。然后套用BIT,其他的跟动态第K大的写法几乎一样。另外就是先用邻接链表记一下每个团队,将每个团队当做一个询问,每次攻击完就扫一遍链表,安置询问位置,这依旧是跟队列长度有关,所以不会退化。对于-1就多加一轮判一下就行了。
那假如修改不在询问之后,直接个体二分行不行呢?当然会超时,这是O(nKlogm)O(nKlogm)的,就是个暴力。
话说这数据有点水,没开long long也能过。。。
代码
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <cmath>
#define N 300010using namespace std;int nG, n, m, K;
int head_p[N], cur, BIT[N], ans[N], S[N];
int qL[N], qR[N], q[N];
bool Left[N];struct Data{int x, y, C;
}attack[N];struct Aadj{int next, obj;
}Edg[N];void Insert(int a, int b){cur ++;Edg[cur].next = head_p[a];Edg[cur].obj = b;head_p[a] = cur;
}int lowbit(int x){return x & (-x);
}void Add(int x, int v){for(int i = x; i <= m; i += lowbit(i)) BIT[i] += v;
}int Sum(int x){int res = 0;for(int i = x; i > 0; i -= lowbit(i)) res += BIT[i];return res;
}void Binary(int L, int R, int he, int ta){if(he > ta) return;if(L == R){for(int i = he; i <= ta; i++){int tmp = q[i];ans[tmp] = L;}return;}int mid = (L + R) >> 1;for(int i = L; i <= mid; i++){if(attack[i].x <= attack[i].y) Add(attack[i].x, attack[i].C), Add(attack[i].y+1, -attack[i].C);else Add(attack[i].x, attack[i].C), Add(1, attack[i].C), Add(attack[i].y+1, -attack[i].C);}for(int i = he; i <= ta; i++){int tmp = q[i], res = 0;for(int j = head_p[tmp]; ~ j; j = Edg[j].next){int v = Edg[j].obj;res += Sum(v);}if(res >= S[tmp]) Left[i] = true;else S[tmp] -= res;}for(int i = L; i <= mid; i++){if(attack[i].x <= attack[i].y) Add(attack[i].x, -attack[i].C), Add(attack[i].y+1, attack[i].C);else Add(attack[i].x, -attack[i].C), Add(1, -attack[i].C), Add(attack[i].y+1, attack[i].C);}int cnt1 = 0, cnt2 = 0;for(int i = he; i <= ta; i++){int tmp = q[i];if(Left[i]) qL[++cnt1] = tmp;else qR[++cnt2] = tmp;Left[i] = false;}for(int i = 1; i <= cnt1; i++) q[he+i-1] = qL[i];for(int i = 1; i <= cnt2; i++) q[he+cnt1+i-1] = qR[i];Binary(L, mid, he, he+cnt1-1);Binary(mid+1, R, he+cnt1, ta);
}int main(){freopen("2202.in", "r", stdin);freopen("2202.out", "w", stdout);scanf("%d", &nG);while(nG --){scanf("%d%d", &n, &m);cur = -1;for(int i = 1; i <= n; i++) head_p[i] = -1;int x;for(int i = 1; i <= m; i++) scanf("%d", &x), Insert(x, i);for(int i = 1; i <= n; i++) scanf("%d", &S[i]);scanf("%d", &K);for(int i = 1; i <= K; i++) scanf("%d%d%d", &attack[i].x, &attack[i].y, &attack[i].C);for(int i = 1; i <= n; i++) q[i] = i;Binary(1, K+1, 1, n);for(int i = 1; i <= n; i++){if(ans[i] == K+1) ans[i] = -1;printf("%d\n", ans[i]);}}return 0;
}
还会有人让你睡不着
还能为某人燃烧
SMOJ 2202 怪物 (整体二分+BIT)相关推荐
- SP3946 MKTHNUM - K-th Number(整体二分)
思路 整体二分的板子题,没什么思路好说 代码 #include <cstdio> #include <algorithm> #include <cstring> u ...
- BZOJ2738 矩阵乘法 【整体二分 + BIT】
题目链接 BZOJ2738 题解 将矩阵中的位置取出来按权值排序 直接整体二分 + 二维BIT即可 #include<algorithm> #include<iostream> ...
- [bzoj2527][Poi2011]Meteors_整体二分_树状数组
Meteors bzoj-2527 Poi-2011 题目大意:题目链接. 注释:略. 想法: 首先答案可以离线,且具有单调性. 这里的单调性就是随着时间的推移,每个国家收集的陨石数增加. 不难想到整 ...
- 【BZOJ2738】矩阵乘法 [整体二分][树状数组]
矩阵乘法 Time Limit: 20 Sec Memory Limit: 256 MB [Submit][Status][Discuss] Description 给你一个N*N的矩阵,不用算矩阵 ...
- 洛谷1527(bzoj2738)矩阵乘法——二维树状数组+整体二分
题目:https://www.luogu.org/problemnew/show/P1527 不难想到(?)可以用二维树状数组.但维护什么?怎么查询是难点. 因为求第k小,可以考虑记权值树状数组,把比 ...
- 【BZOJ1146】【CTSC2008】网络管理 [整体二分]
网络管理 Time Limit: 50 Sec Memory Limit: 162 MB [Submit][Status][Discuss] Description M公司是一个非常庞大的跨国公司, ...
- 【bzoj4009】[HNOI2015]接水果 DFS序+树上倍增+整体二分+树状数组
题目描述 给出一棵n个点的树,给定m条路径,每条路径有一个权值.q次询问求一个路径包含的所有给定路径中权值第k小的. 输入 第一行三个数 n和P 和Q,表示树的大小和盘子的个数和水果的个数. 接下来n ...
- 洛谷P1527 [国家集训队] 矩阵乘法 [整体二分,二维树状数组]
题目传送门 矩阵乘法 题目描述 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. 输入输出格式 输入格式: 第一行两个数N,Q,表示矩阵大小和询问组数: 接下来N行N列一共N* ...
- P3242 [HNOI2015] 接水果(整体二分、扫描线)
P3242 [HNOI2015] 接水果 给定一棵树,定义给定了ppp个盘子,每个盘子是树上u,vu, vu,v两点的路径,且盘子有权值,定义水果,水果也是树上u,vu, vu,v两点间的路径. 有q ...
最新文章
- 软件的复用技术及开发方法
- uni-app接口封装
- Nginx在Windows上启动、停止的命令
- Oracle入门(十三A2)之单行函数
- jcmd_程序化JCMD访问
- aip格式转化为pdf_python提取pdf文档中的表格数据、svg格式转换为pdf
- 转, C# 如何在MVC3中取消备用控制器的选择
- 微软发布 Autodesk FBX 漏洞带外安全公告,将于5月推出补丁
- 覆盖索引与联合索引_MySQL:你知道什么是覆盖索引吗?
- 《Redis实战》一2.2 使用Redis实现购物车
- ArcGIS API 4.x 加载高德底图
- outlook如何设置qq邮箱服务器,qq邮箱关联outlook
- 如何获取 Boot Camp for Windows(Mac电脑装Windows后如何安装驱动)
- 教你恢复电脑被删的照片或视频,方法实用可收藏
- linux罗马数字1到10怎么打,罗马数字怎么打
- win10自带安全中心关闭方法
- 【BZOJ】【3053】The Closest M Points
- 使用高德地图api在页面中展示地图
- 软考-高项-论文-信息系统项目的人力资源管理
- 当你写爬虫抓不到APP请求包的时候该怎么办?【高级篇-混淆导致通用Hook工具失效】