牛客多校第三场 G Removing Stones(分治+线段树)
牛客多校第三场 G Removing Stones(分治+线段树)
题意:
给你n个数,问你有多少个长度不小于2的连续子序列,使得其中最大元素不大于所有元素和的一半
题解:
分治+线段树
线段树维护最大值的位置,每次分治找就找这个最大值,然后看最大值在哪个序列是可行的
怎么看最大值所在的序列是否可行呢?
我们用一个前缀和维护区间和
2*max-(sum[r]-sum[l])<=0\\
\]
这个最大值在这一段区间内都有可能出现
为了得到总的方案数
我们在当前区间内枚举靠近最大值出现的位置pos的那一段,然后二分右\左端点,即可得到一段最小的区间[i,t]或者[t,i]可以满足 区间内最大元素不大于所有元素和的一半的条件,然后计数就加上容斥后的r-t+1或者t-l+1这一段即可
代码:
/**
* ┏┓ ┏┓
* ┏┛┗━━━━━━━┛┗━━━┓
* ┃ ┃
* ┃ ━ ┃
* ┃ > < ┃
* ┃ ┃
* ┃... ⌒ ... ┃
* ┃ ┃
* ┗━┓ ┏━┛
* ┃ ┃ Code is far away from bug with the animal protecting
* ┃ ┃ 神兽保佑,代码无bug
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┃
* ┃ ┗━━━┓
* ┃ ┣┓
* ┃ ┏┛
* ┗┓┓┏━┳┓┏┛
* ┃┫┫ ┃┫┫
* ┗┻┛ ┗┻┛
*/
// warm heart, wagging tail,and a smile just for you!
//
// _ooOoo_
// o8888888o
// 88" . "88
// (| -_- |)
// O\ = /O
// ____/`---'\____
// .' \| |// `.
// / \||| : |||// \
// / _||||| -:- |||||- \
// | | \ - /// | |
// | \_| ''\---/'' | |
// \ .-\__ `-` ___/-. /
// ___`. .' /--.--\ `. . __
// ."" '< `.___\_<|>_/___.' >'"".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `-. \_ __\ /__ _/ .-` / /
// ======`-.____`-.___\_____/___.-`____.-'======
// `=---='
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
// 佛祖保佑 永无BUG
#include <set>
#include <map>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long uLL;
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define bug printf("*********\n")
#define FIN freopen("input.txt","r",stdin);
#define FON freopen("output.txt","w+",stdout);
#define IO ios::sync_with_stdio(false),cin.tie(0)
#define debug1(x) cout<<"["<<#x<<" "<<(x)<<"]\n"
#define debug2(x,y) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<"]\n"
#define debug3(x,y,z) cout<<"["<<#x<<" "<<(x)<<" "<<#y<<" "<<(y)<<" "<<#z<<" "<<z<<"]\n"
const int maxn = 3e5 + 5;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double Pi = acos(-1);
LL gcd(LL a, LL b) {
return b ? gcd(b, a % b) : a;
}
LL lcm(LL a, LL b) {
return a / gcd(a, b) * b;
}
double dpow(double a, LL b) {
double ans = 1.0;
while(b) {
if(b % 2)ans = ans * a;
a = a * a;
b /= 2;
} return ans;
}
LL quick_pow(LL x, LL y) {
LL ans = 1;
while(y) {
if(y & 1) {
ans = ans * x % mod;
} x = x * x % mod;
y >>= 1;
} return ans;
}
pii Max[maxn << 2];
LL sum[maxn];
int a[maxn];
void push_up(int rt) {
Max[rt] = max(Max[ls], Max[rs]);
}
void build(int l, int r, int rt) {
if(l == r) {
Max[rt] = make_pair(a[l], l);
return;
}
int mid = (l + r) >> 1;
build(lson);
build(rson);
push_up(rt);
}
pii query(int L, int R, int l, int r, int rt) {
if(L <= l && r <= R) {
return Max[rt];
}
int mid = (l + r) >> 1;
pii ans = make_pair(0, 0);
if(L <= mid) ans = max(ans, query(L, R, lson));
if(R > mid) ans = max(ans, query(L, R, rson));
return ans;
}
//二分最短区间大于后缀
int find1(int l, int r, LL x) {
int L = l, R = r + 1, res = l - 1;
while (L <= R) {
int mid = (L + R) >> 1;
if (sum[r] - sum[mid - 1] >= x) {
L = mid + 1;
res = mid;
} else R = mid - 1;
}
return res;
}
int find2(int l, int r, LL x) {
int L = l - 1, R = r, res = r + 1;
while (L <= R) {
int mid = (L + R) >> 1;
if (sum[mid] - sum[l - 1] >= x) {
R = mid - 1;
res = mid;
} else L = mid + 1;
}
return res;
}
LL ans = 0;
int n;
void solve(int l, int r) {
if(l == r) return;
int mid = query(l, r, 1, n, 1).second;
if(l < mid) solve(l, mid - 1);
if(r > mid) solve(mid + 1, r);
if(mid - l < r - mid) {
for(int i = l; i <= mid; i++) {
int t = find2(mid + 1, r, 2 * a[mid] - (sum[mid] - sum[i - 1]));
ans += r - t + 1;
}
} else {
for(int i = mid; i <= r; i++) {
int t = find1(l, mid - 1, 2 * a[mid] - (sum[i] - sum[mid - 1]));
ans += t - l + 1;
}
}
}
int main() {
#ifndef ONLINE_JUDGE
FIN
#endif
int T;
scanf("%d", &T);
while(T--) {
scanf("%d", &n);
sum[0] = 0;
ans = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
sum[i] = sum[i - 1] + a[i];
}
build(1, n, 1);
solve(1, n);
printf("%lld\n", ans);
}
return 0;
}
牛客多校第三场 G Removing Stones(分治+线段树)的更多相关文章
- [2019牛客多校第三场][G. Removing Stones]
题目链接:https://ac.nowcoder.com/acm/contest/883/G 题目大意:有\(n\)堆石头,每堆有\(a_i\)个,每次可以选其中两堆非零的石堆,各取走一个石子,当所有 ...
- 2019牛客多校第八场 F题 Flowers 计算几何+线段树
2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...
- 牛客多校第十场 A Rikka with Lowbit 线段树
链接:https://www.nowcoder.com/acm/contest/148/A来源:牛客网 题目描述 Today, Rikka is going to learn how to use B ...
- 牛客多校第四场 J.Hash Function(线段树优化建图+拓扑排序)
题目传送门:https://www.nowcoder.com/acm/contest/142/J 题意:给一个hash table,求出字典序最小的插入序列,或者判断不合法. 分析: eg.对于序列{ ...
- Removing Stones(2019年牛客多校第三场G+启发式分治)
目录 题目链接 题意 思路 代码 题目链接 传送门 题意 初始时有\(n\)堆石子,每堆石子的石子个数为\(a_i\),然后进行游戏. 游戏规则为你可以选择任意两堆石子,然后从这两堆中移除一个石子,最 ...
- 启发式分治:2019牛客多校第三场 G题 Removing Stones
问题可以转换为求有多少个区间数字的总和除2向下取整大于等于最大值.或者解释为有多少个区间数字的总和大于等于最大值的两倍(但是若区间数字总和为奇数,需要算作减1) 启发式分治: 首先按最大值位置分治,遍 ...
- 牛客多校第三场 F Planting Trees
牛客多校第三场 F Planting Trees 题意: 求矩阵内最大值减最小值大于k的最大子矩阵的面积 题解: 矩阵压缩的技巧 因为对于我们有用的信息只有这个矩阵内的最大值和最小值 所以我们可以将一 ...
- 牛客多校第四场 G Maximum Mode
链接:https://www.nowcoder.com/acm/contest/142/G来源:牛客网 The mode of an integer sequence is the value tha ...
- 牛客多校第三场 A—pacm team (4维背包加路径压缩)
链接:https://www.nowcoder.com/acm/contest/141/A 来源:牛客网 Eddy was a contestant participating , Eddy fail ...
随机推荐
- PHP汉字验证码
转自:http://www.blhere.com/1167.html 12345678910111213141516171819202122232425262728293031323334353637 ...
- windows下多版本python安装与pip安装和pip使用 吐血总结
https://blog.csdn.net/silence2015/article/details/56483892/ 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附 ...
- Person Re-identification 系列论文笔记(一):Scalable Person Re-identification: A Benchmark
打算整理一个关于Person Re-identification的系列论文笔记,主要记录近年CNN快速发展中的部分有亮点和借鉴意义的论文. 论文笔记流程采用contributions->algo ...
- BZOJ 1008 越狱题解
其实这题很水,显然n个房间有m种宗教,总共有n^m种情况, 我们再考虑不合法的情况,显然第一个房间有m种情况,而后一种只有m-1种情况(因为不能相同) 所以不合法的情况有(m-1)^(n-1)*m种情 ...
- GIAC2019 演讲精选 | 面向未来的黑科技——UI2CODE闲鱼基于图片生成跨端代码
一直以来, 如何从‘视觉稿’精确的还原出 对应的UI侧代码 一直是端侧开发同学工作里消耗比较大的部分,一方面这部分的工作 比较确定缺少技术深度,另一方面视觉设计师也需要投入大量的走查时间,有大量无谓的 ...
- sum(),max(),avg(),RATIO_TO_REPORT()--分组统计
select id,area, sum(1) over() as 总记录数, sum(1) over(partition by id) as 分组记录数, sum(score) over() as 总 ...
- @codeforces - 1221G@ Graph And Numbers
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个 n 点 m 边的无向图. 现在要求给每个点写上 0 或 ...
- Redis源码解析:03字典
字典是一种用于保存键值对(key value pair)的抽象数据结构.在字典中,一个键和一个值进行关联,就是所谓的键值对.字典中的每个键都是独一无二的,可以根据键查找.更新值,或者删除整个键值对等等 ...
- 03寻找最小的k个数
题目描述:查找最小的k个元素 题目:输入n个整数,输出其中最小的k个. 例如输入1,2,3,4,5,6,7和8这8个数字,则最小的4个数字为1,2,3和4. 1:最简单 ...
- @loj - 6353@「CodePlus 2018 4 月赛」组合数问题 2
目录 @description@ @solution@ @accepted code@ @details@ @description@ 请你找到 k 个不同的组合数,使得对于其中任何一个组合数 \(C ...