[jzoj5073 GDOI2017第二轮模拟] 影魔

Description

影魔,奈文摩尔,据说有着一个诗人的灵魂。事实上,他吞噬的诗人灵魂早已成千上万。千百年来,他收集了各式各样的灵魂,包括诗人、牧师、帝王、乞丐、奴隶、罪人,当然,还有英雄。
每一个灵魂,都有着自己的战斗力,而影魔,靠这些战斗力提升自己的攻击。
奈文摩尔有n个灵魂,他们在影魔宽广的体内可以排成一排,从左至右标号1到n。第i个灵魂的战斗力为k[i],灵魂们以点对的形式为影魔提供攻击力,对于灵魂对i,j(i<j)来说,若不存在k[s](i<s<j)大于k[i]或者k[j],则会为影魔提供p1的攻击力(可理解为:当j=i+1时,因为不存在满足i<s<j的s,从而k[s]不存在,这时提供p1的攻击力;当j>i+1时,若max{k[s]|i<s<j}<=min{k[i],k[j]},则提供p1的攻击力);另一种情况,令c为k[i+1],k[i+2],k[i+3]……k[j-1]的最大值,若c满足:k[i]<c<k[j],或者k[j]<c<k[i],则会为影魔提供p2的攻击力,当这样的c不存在时,自然不会提供这p2的攻击力;其他情况的点对,均不会为影魔提供攻击力。
影魔的挚友噬魂鬼在一天造访影魔体内时被这些灵魂吸引住了,他想知道,对于任意一段区间[a,b],1<=a<b<=n,位于这些区间中的灵魂对会为影魔提供多少攻击力,即考虑所有满足a<=i<j<=b的灵魂对i,j提供的攻击力之和。
顺带一提,灵魂的战斗力组成一个1到n的排列:k[1],k[2],…,k[n]。

Input

输入文件名为sf.in。
第一行n,m,p1,p2
第二行n个数:k[1],k[2],…,k[n]
接下来m行,每行两个数a,b,表示询问区间[a,b]中的灵魂对会为影魔提供多少攻击力。

Output

输出文件名为sf.out
共输出m行,每行一个答案,依次对应m个询问。

Sample Input

10 5 2 3
7 9 5 1 3 10 6 8 2 4
1 7
1 9
1 3
5 9
1 5 

Sample Output

30
39
4
13
16

Data Constraint

30%:1<= n,m <= 500。
另30%: p1=2*p2。
100%:1 <= n,m <= 200000;1 <= p1,p2 <= 1000。

Solution

把所有询问离线

用单调栈分别做两次,求出对于排列数组的单个元素从自己开始到左边和到右边的最远的端点

为了处理贡献对应询问的区间建出一颗线段树

按左端点排序询问,枚举区间内的元素,设当前元素为最大值,那么,从它到区间端点(端点作为最大值)的这个区间的都可以打上p2贡献的标记

设当前元素为次小值,那么,对区间端点打上p1-p2-p2的标记(作为次小有两次重复)

#include <stdio.h>
#include <string.h>
#include <algorithm>
#define _L long long
#define _RG register int
#define lson s, mid, k << 1
#define rson mid + 1, t, k << 1 | 1
const int N = 200010;
int n, m, p1, p2, a[N], l[N], r[N], steck[N], sec, nex[N], tim;
_L tag[N << 2], sum[N << 2], ans[N];
struct Q
	{
	int l, r, id;
	}que[N];
inline void downt(_RG s, _RG t, _RG k)
	{
	sum[k] += tag[k] * (_L)(t - s + 1);
	if(s ^ t) tag[k << 1] += tag[k], tag[k << 1 | 1] += tag[k];
	tag[k] = 0;
	}
void updat(_RG s, _RG t, _RG k, _RG x, _RG y, _RG z)
	{
	_RG mid = s + t >> 1;
	downt(s, t, k);
	if(s ^ t) downt(s, mid, k << 1), downt(mid + 1, t, k << 1 | 1);
	if(s == x && t == y)
		{
		tag[k] += z;
		downt(s, t, k);
		return;
		}
	if(y <= mid) updat(lson, x, y, z);
	else if(x > mid) updat(rson, x, y, z);
	else updat(lson, x, mid, z), updat(rson, mid + 1, y, z);
	sum[k] = sum[k << 1] + sum[k << 1 | 1];
	}
_L query(_RG s, _RG t, _RG k, _RG x, _RG y)
	{
	_RG mid = s + t >> 1;
	downt(s, t, k);
	if(s ^ t) downt(s, mid, k << 1), downt(mid + 1, t, k << 1 | 1);
	if(s == x && t == y) return sum[k];
	if(y <= mid) return query(lson, x, y);
	if(x > mid) return query(rson, x, y);
	return query(lson, x, mid) + query(rson, mid + 1, y);
	}
void solve()
	{
	for(_RG i = 1; i <= m; ++i) que[i] = (Q) {l[i], r[i], i};
	std::sort(que + 1, que + 1 + m, [](const Q &u, const Q &v) {return u.l > v.l;});
	steck[sec = 1] = n + 1;
	a[n + 1] = 1e9;
	for(_RG i = n; i; --i)
		{
		while(sec && a[steck[sec]] < a[i]) --sec;
		nex[i] = steck[sec];
		steck[++sec] = i;
		}
	tim = 1;
	for(_RG i = n; i; --i)
		{
		updat(1, n + 1, 1, i + 1, nex[i], p2);
		updat(1, n + 1, 1, nex[i], nex[i], p1 - p2 - p2);
		while(tim <= m && que[tim].l == i)
			{
			ans[que[tim].id] += query(1, n + 1, 1, i, que[tim].r);
			++tim;
			}
		if(tim > m) break;
		}
	}
int main()
	{
	scanf("%d%d%d%d", &n, &m, &p1, &p2);
	for(_RG i = 1; i <= n; ++i) scanf("%d", a + i);
	for(_RG i = 1; i <= m; ++i) scanf("%d%d", l + i, r + i);
	solve();
	memset(sum, 0LL, sizeof sum), memset(tag, 0LL, sizeof tag);
	for(_RG i = 1; i <= n / 2; ++i) std::swap(a[i], a[n - i + 1]);
	for(_RG i = 1; i <= m; ++i) l[i] = n - l[i] + 1, r[i] = n - r[i] + 1, std::swap(l[i], r[i]);
	solve();
	for(_RG i = 1; i <= m; ++i) printf("%lld\n", ans[i]);
	return 0;
	}

  

枚举当前数为次小值,则可以直接为区间加上贡献,用线段树覆盖,

时间: 2024-11-05 04:19:46

[jzoj5073 GDOI2017第二轮模拟] 影魔的相关文章

【百度之星2014~初赛(第二轮)解题报告】Chess

声明 笔者最近意外的发现 笔者的个人网站http://tiankonguse.com/ 的很多文章被其它网站转载,但是转载时未声明文章来源或参考自 http://tiankonguse.com/ 网站,因此,笔者添加此条声明. 郑重声明:这篇记录<[百度之星2014~初赛(第二轮)解题报告]Chess>转载自 http://tiankonguse.com/ 的这条记录:http://tiankonguse.com/record/record.php?id=667 前言 最近要毕业了,有半年没做

【百度之星2014~初赛(第二轮)解题报告】JZP Set

声明 笔者最近意外的发现 笔者的个人网站http://tiankonguse.com/ 的很多文章被其它网站转载,但是转载时未声明文章来源或参考自 http://tiankonguse.com/ 网站,因此,笔者添加此条声明. 郑重声明:这篇记录<[百度之星2014~初赛(第二轮)解题报告]JZP Set>转载自 http://tiankonguse.com/ 的这条记录:http://tiankonguse.com/record/record.php?id=668 前言 最近要毕业了,有半年

2014年百度之星程序设计大赛 - 初赛(第二轮)

1001 暴力 #include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int maxn = 100100; int ll[maxn], rr[maxn]; struct node { int x, y, bj; }e[maxn]; int main() { int cas = 1; int T; scanf("%d", &T);

团队项目冲刺第二轮——第一天

今天是第二轮团队冲刺的第一天,上次的团队成果其实并不让人满意,而且在后期出现了很大的问题.总结一下原因其实是我们只管自己独立的任务,相互之间缺乏必要的交流,其实三个人在一起编程的时间根本没有多少,大多是自己一个人.这就造成了有了想法不能与团队成员及时沟通,只能开发那些相互之间联系不大的部分,结果就是最后的整合浪费了我们大量的时间,更没时间去拓展新的功能.在这次团队冲刺中,应该极力避免上次的错误. 第二轮冲刺相对于第一次的项目要有很大的改动,所以今天我们团队重新从头到尾讨论了一下项目,明确目标之后

2014年百度之星程序设计大赛 - 初赛(第二轮)Chess

题目描述:小度和小良最近又迷上了下棋.棋盘一共有N行M列,我们可以把左上角的格子定为(1,1),右下角的格子定为(N,M).在他们的规则中,"王"在棋盘上的走法遵循十字路线.也就是说,如果"王"当前在(x,y)点,小度在下一步可以移动到(x+1, y), (x-1, y), (x, y+1), (x, y-1), (x+2, y), (x-2, y), (x, y+2), (x, y-2) 这八个点中的任意一个. 小度觉得每次都是小良赢,没意思.为了难倒小良,他想出

第六届华为创新杯编程大赛第二轮(2014.4.29)

第一题:外星人比数的大小 来自星星的都教授除了所有感官比地球人高出七倍,始终容颜不老以外,还拥有一项在地球人看来特别神奇的能力,他会瞬间(0.00000000000000000000001s以内)按照他的规则比较地球人熟悉的两个十进制数字的大小,他比较的规则如下:1.将要比较的两个数字分别转换成二进制数字:2.计算两个二进制数字中1的个数,个数多的数字为两者中的大者:3.负数按照其绝对值进行比较:请利用地球人发明的计算机程序逼近都教授的特异功能,实现时可以有以下约束:1.输入数据为范围在-327

腾讯Java程序员第二轮面试11个问题,你会几个?

此前,分享了阿里巴巴.网易.百度等多家名企的JAVA面试题. 这也引来了不少程序员网友们的围观. 其中,也有相当一部分网友是已经从事Java开发好多年的程序员,当他们阅读完JAVA面试题的反应是:一个也不会. 通常这种类型的程序员已经将编程转换成了一种技能,而不是在脑海里的知识. 有人认为,面试造火箭,进去拧螺丝. 当然,也有中途放弃编程的程序员,Java从入门到放弃. 但无论如何,编程这条路总是有人在走. 也只有一种人在编程界可以混得风生水起:对编程感兴趣,能够把编程做到极致的人. 下面我给程

小米Java程序员第二轮面试10个问题,你是否会被刷掉?

近日,开发者头条上分享了一篇"小米java第二轮面经",有很多的java程序员表示非常有兴趣. 下面l就和各位分享小米java第二轮面经(华为java工程师笔试面试题可以看文章某尾): 0.谈谈对Spring的认识 1.java集合的继承关系 2.你知道CLOSE_WAIT这个状态吗? 3.谈谈你对jvm.java内存模型的认识? 4.Java里的红黑树是怎么实现的? 5.谈一下对strust2的理解 6.IOC最大的好处是什么呢? 7.长连接与短连接有什么区别? 8.HashMap怎

第二轮面试

第二轮面试题 1.SSM的开发步骤是什么? 2.设计一个权限模块? 3.什么是docker? 4.什么是dockfile? 5.什么是docker-compose? 6.什么是Portainer? 7.在公司里使用的docker的版本是什么? 8.镜像和容器的关系? 9.分布式锁中的基于redis的setnx的原理以及set和setnx的区别是什么? 10.什么是springcloud,springcloud中的组件有哪些?分别描述下它的原理? 11.什么是jmeter? 一.SSM的开发步骤是