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


    传送门


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


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

    $sumlimits_{L leqslant i leqslant j leqslant R}frac{ extrm{min}_{i cdots j} + extrm{max}_{i cdots j}}{2} / frac{len * (len + 1)}{2} extrm{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;
    }
    
  • 相关阅读:
    BZOJ 3156 防御准备
    codevs 1033 蚯蚓的游戏问题
    BZOJ 3669 【NOI2014】 魔法森林
    分享知识-快乐自己:全面解析 java注解实战指南
    分享知识-快乐自己:MySQL中的约束,添加约束,删除约束,以及一些其他修饰
    分享知识-快乐自己:Oracle基本语法(创建:表空间、用户、授权、约束等)使用指南
    分享知识-快乐自己: Oracle数据库实例、用户、表、表空间之间关系
    分享知识-快乐自己:oracle12c创建用户提示ORA-65096:公用用户名或角色无效
    分享知识-快乐自己:论 Mybatis中的关联关系(一对多,多对一,多对多)
    分享知识-快乐自己:JAVA中的 Iterator 和 Iterable 区别
  • 原文地址:https://www.cnblogs.com/mrclr/p/15083830.html
Copyright © 2020-2023  润新知