HDU6989 Didn't I Say to Make My Abilities Average in the Next Life?!

传送门


这题比赛的时候虽然做的人相对较多,但是自己根本没有什么头绪。


一句话题意:\(n\)个数,\(m\)个询问,每次让你求

$\sum\limits_{L \leqslant i \leqslant j \leqslant R}\frac{\textrm{min}_{i \cdots j} \ \ \ \ + \ \ \textrm{max}_{i \cdots j}}{2} / \frac{len * (len + 1)}{2} \ \ \textrm{mod} \ \ 10^9+7$.

题解给了个线段树的乱七八糟的十分复杂的算法,没看懂。顾子哥给我推荐了一道几乎一模一样的题,洛谷上第一篇题解妙的很,所以直接看我的这篇题解吧。


那这道题就是要分别求一遍最大值和最小值罢了。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<queue>
#include<assert.h>
#include<ctime>
using namespace std;
#define enter puts("") 
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
#define forE(i, x, y) for(int i = head[x], y; ~i && (y = e[i].to); i = e[i].nxt)
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 2e5 + 5;
const int N = 18;
const ll mod = 1e9 + 7;
In ll read()
{
	ll ans = 0;
	char ch = getchar(), las = ' ';
	while(!isdigit(ch)) las = ch, ch = getchar();
	while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
	if(las == '-') ans = -ans;
	return ans;
}
In void write(ll x)
{
	if(x < 0) x = -x, putchar('-');
	if(x >= 10) write(x / 10);
	putchar(x % 10 + '0');
}
In void MYFILE()
{
#ifndef mrclr
	freopen("1005.in", "r", stdin);
	freopen("ha.out", "w", stdout);
#endif
}

In ll ADD(ll a, ll b) {return a + b < mod ? a + b : a + b - mod;}
In ll quickpow(ll a, ll b)
{
	ll ret = 1;
	for(; b; b >>= 1, a = a * a % mod)
		if(b & 1) ret = ret * a % mod;
	return ret;
}

int n, m, a[maxn];

struct Node
{
	ll f[maxn], sum[maxn];
}MIN[2], MAX[2];
int st[maxn], top = 0, pre[maxn];
In void calc(Node& A, int flg)
{
	top = 0;
	for(int i = n; i; --i)
	{
		while(top && a[i] <= a[st[top]]) pre[st[top--]] = i;
		st[++top] = i;
	}
	while(top) pre[st[top--]] = 0;
	for(int i = 1; i <= n; ++i) A.f[i] = ADD(A.f[pre[i]], 1LL * flg * a[i] * (i - pre[i]) % mod);
	for(int i = 1; i <= n; ++i) A.sum[i] = ADD(A.sum[i - 1], A.f[i]);	
}
int dp[maxn][N + 2][2], ha[maxn];
In void rmq_init()
{
	for(int i = 1; i <= n; ++i) dp[i][0][0] = dp[i][0][1] = i;
	for(int j = 1; (1 << j) <= n; ++j)
		for(int i = 1; i + (1 << j) - 1 <= n; ++i)
		{
			int tp1 = dp[i][j - 1][0], tp2 = dp[i + (1 << (j - 1))][j - 1][0];
			dp[i][j][0] = a[tp1] < a[tp2] ? tp1 : tp2;
			tp1 = dp[i][j - 1][1], tp2 = dp[i + (1 << (j - 1))][j - 1][1];
			dp[i][j][1] = a[tp1] > a[tp2] ? tp1 : tp2;			
		}
	for(int i = 2; i <= n; ++i) ha[i] = ha[i >> 1] + 1;
}
#define pr pair<int, int>
#define F first
#define S second
In pr query(int L, int R)
{
	int k = ha[R - L + 1];
	int tp1 = dp[L][k][0], tp2 = dp[R - (1 << k) + 1][k][0];
	int ret1 = a[tp1] < a[tp2] ? tp1 : tp2;
	tp1 = dp[L][k][1], tp2 = dp[R - (1 << k) + 1][k][1];
	int ret2 = a[tp1] > a[tp2] ? tp1 : tp2;	
	return make_pair(ret1, ret2);
}

In void solve()
{
	calc(MIN[0], 1);
	reverse(a + 1, a + n + 1);
	calc(MIN[1], 1);
	reverse(MIN[1].f + 1, MIN[1].f + n + 1);
	reverse(MIN[1].sum + 1, MIN[1].sum + n + 1);
	reverse(a + 1, a + n + 1);
	for(int i = 1; i <= n; ++i) a[i] = -a[i];
	calc(MAX[0], -1);
	reverse(a + 1, a + n + 1);
	calc(MAX[1], -1);
	reverse(MAX[1].f + 1, MAX[1].f + n + 1);
	reverse(MAX[1].sum + 1, MAX[1].sum + n + 1);
	reverse(a + 1, a + n + 1);
	for(int i = 1; i <= n; ++i) a[i] = -a[i];
	rmq_init();
	
	for(int i = 1; i <= m; ++i)
	{
		int L = read(), R = read(), len = R - L + 1;
		pr tp = query(L, R); int p1 = tp.F, p2 = tp.S;
		ll ans1 = MIN[0].sum[R] - MIN[0].sum[p1] - MIN[0].f[p1] * (R - p1) % mod;
		ans1 = ADD(ans1 % mod, mod);
		ll ans2 = MIN[1].sum[L] - MIN[1].sum[p1] - MIN[1].f[p1] * (p1 - L) % mod;
		ans2 = ADD(ans2 % mod, mod);
		ll ANS1 = ADD(1LL * a[p1] * (R - p1 + 1) % mod * (p1 - L + 1) % mod, ADD(ans1, ans2));
		ans1 = MAX[0].sum[R] - MAX[0].sum[p2] - MAX[0].f[p2] * (R - p2) % mod;
		ans1 = ADD(ans1 % mod, mod);
		ans2 = MAX[1].sum[L] - MAX[1].sum[p2] - MAX[1].f[p2] * (p2 - L) % mod;
		ans2 = ADD(ans2 % mod, mod);
		ll ANS2 = ADD(1LL * a[p2] * (R - p2 + 1) % mod * (p2 - L + 1) % mod, ADD(ans1, ans2));
		write(ADD(ANS1, ANS2) * quickpow(1LL * len * (len + 1) % mod, mod - 2) % mod), enter; 
	}
}

int main()
{
//	MYFILE();
	int T = read();
	while(T--)
	{
		n = read(), m = read();
		for(int i = 1; i <= n; ++i) a[i] = read();
		solve();
	}
	return 0;
}
上一篇:20201217-2 类变量的作用及析构函数


下一篇:答疑代码问题