牛客挑战赛30 B 小A的排列___枚举+链表

206 篇文章 0 订阅
3 篇文章 0 订阅

题目大意:

给出一个长度为n的全排列 p p p
m i d l , r mid_{l,r} midl,r为全排列中区间 [ l , r ] [l,r] [l,r]的中位数,
2 ∗ ∑ l = 1 n ∑ r = l n s e e d ( l − 1 ) ∗ n + r m i d l , r 2*\sum_{l=1}^{n}\sum_{r=l}^{n}seed^{(l-1)*n+r}mid_{l,r} 2l=1nr=lnseed(l1)n+rmidl,r
答案对 1 e 9 + 7 1e9+7 1e9+7取模。
在这里插入图片描述
n ≤ 1 e 4 , s e e d &lt; 1 e 9 + 7 n≤1e4,seed&lt;1e9+7 n1e4seed<1e9+7

分析:

提前处理出 s e e d n seed^n seedn,设为 s e e d n u m seednum seednum
枚举右端点 r r r r r r为排列 p p p中某个位置
[ 1 , r ] [1,r] [1,r]建立链表S,不是 P [ l . . r ] P[l..r] P[l..r],是数 [ l , r ] [l,r] [l,r] S r S_{r} Sr可以由 S r + 1 S_{r+1} Sr+1删掉数 p r + 1 p_{r+1} pr+1
T T T= S r S_{r} Sr
然后从左到右的枚举左端点 l l l
每次用链表维护一下中位数就可以,因为可以数列长度为偶数,那么我们令 m i d 1 , m i d 2 mid_1,mid_2 mid1,mid2表示2个中位数分别的位置,如果数列长度为奇数,则 m i d 1 = m i d 2 mid1=mid2 mid1=mid2
每次 l + 1 l+1 l+1都将 T T T中的 p l p_{l} pl删掉,
s e e d ( l − 1 ) ∗ n + r seed^{(l-1)*n+r} seed(l1)n+r可以通过 s e e d n seed^n seedn的预处理在每次 l + 1 l+1 l+1时O(1)计算,每次维护链表都是 O ( 1 ) O(1) O(1)
然后这题就搞完了
时间复杂度是 O ( n 2 ) O(n^2) O(n2)

代码:

#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map> 
#include <cstring>
#include <algorithm>

#define N 10005

using namespace std;

typedef long long ll;
 
const int mo = 1e9 + 7;

struct Node {
    int pre[N], nxt[N];
    void del(int x)
	{ 
	    nxt[pre[x]] = nxt[x]; 
		pre[nxt[x]] = pre[x];
	}
}S, T;
int p[N], seednum, seed, ans, n;

int power(int x, int y)
{
    int rp = 1;
    for (; y; y >>= 1)
    {
		if (y & 1) rp = (ll)rp * x % mo;
        x = (ll)x * x % mo;
    }
    return rp;
}
 
int main()
{
    scanf("%d %d", &n, &seed);
    for (int i = 1; i <= n; i++) scanf("%d", &p[i]);
    seednum = power(seed, n);
    for(int i = 1; i <= n + 1; i++) S.pre[i] = i - 1, S.nxt[i - 1] = i;
	int pos1 = (n + 1) / 2, pos2 = (n + 2) / 2;
    for (int i = n; i >= 1; i--)
    {
        int posA = pos1, posB = pos2; 
		T = S;
        int now = power(seed, i);
         
        for (int j = 1; j <= i; j++) 
        {
            ans = (ans + (ll)now * (posA + posB) % mo) % mo; 
            if (posA == posB)
            {
                if (p[j] <= posB) posB = T.nxt[posB];
                if (p[j] >= posA) posA = T.pre[posA];
            } 
			else
            {
                if (p[j] <= posA) posA = T.nxt[posA];
                if (p[j] >= posB) posB = T.pre[posB];
            }
            T.del(p[j]);
            now = (ll)now * seednum % mo;
        }
        
        if (pos1 == pos2)
        {
            if (p[i] <= pos2) pos2 = S.nxt[pos2];
            if (p[i] >= pos1) pos1 = S.pre[pos1];
        }
		else
        {
            if (p[i] <= pos1) pos1 = S.nxt[pos1];
            if (p[i] >= pos2) pos2 = S.pre[pos2];
        }
        S.del(p[i]);
    }
    printf("%d\n", ans);
    return 0;
}
Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值