链接:https://ac.nowcoder.com/acm/contest/358/D
来源:牛客网

出题人的手环
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 524288K,其他语言1048576K
64bit IO Format: %lld

题目描述

出题人的妹子送了出题人一个手环,这个手环上有 n 个珠子,每个珠子上有一个数。
有一天,出题人和妹子分手了,想把这个手环从两个珠子间切开,并按顺时针顺序展开成一条链。

可以发现,这条链一共有 n 种可能性。求这 n 种可能性的逆序对数之积模 1000000007。

输入描述:

第一行一个数 n,表示珠子个数。
接下来一行 n 个数,以顺时针顺序给出每个珠子上的整数

输出描述:

一个数,表示答案。
示例1

输入

复制

4
1 3 2 3

输出

复制

24

说明

一共有 4 种方式:
1 3 2 3;3 1 3 2;2 3 1 3;3 2 3 1;
逆序对数分别为 1,3,2,4,积为 24。

备注:

n<=200000,-10^9<=珠子上的整数<=10^9。

思路:
个人觉得还是一个很不错的题目。
首先,因为数值范围比较大,先离散化一下。 (不会离散化的点此去学其次先根据离散化后的数组标记下求一个前缀和,前缀和 sum[i] 维护的是 离散化后的数组(下面成为新数组)中的1~i中累计的个数和,需要多开一个vis数组,
然后先根据树状数组来求出新数组的逆序对的总数。(具体求法和细节看code和注释)
然后我们把当前新数组中的第一个数放在最后一个位置,这样对一个数组的逆序对总和的影响是 减去 2~n位置中小于a[1]的个数,加上2~n位置中大于a[1]的个数,
而这恰好可以用我们刚刚求得前缀和来解决。
然后每一个调整后得数组的总和乘起来,记得取模就好了 (算法学习(二)——树状数组求逆序数
细节见我的代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), '\0', sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define db(x) cout<<"== "<<x<<" =="<<endl;
using namespace std;
typedef long long ll;
inline void getInt(int* p);
const int maxn=;
const int inf=0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
int n;
ll a[maxn];
ll b[maxn];
ll tree[maxn];
ll vis[maxn];
ll sum[maxn];
const ll mod=1000000007ll;
int lowbit(int x)
{
return x&(-*x);
}
void add(int i)
{
while(i<=maxn)
{
tree[i]+=;
i+=lowbit(i);
}
}
ll query(int i)
{
ll res=;
while(i>)
{
res+=tree[i];
i-=lowbit(i); }
return res;
}
int main()
{
gbtb;
cin>>n;
repd(i,,n)
{
cin>>a[i];
b[i]=a[i];
}
sort(b+,b++n);// 辅组数组的排序
int cnt=unique(b+,b++n)-b-; // 去重
repd(i,,n)
{
a[i]=lower_bound(b+,b++cnt,a[i])-b; // 离散化挂的核心code
vis[a[i]]++;// 标记
}
repd(i,,n)
{
sum[i]=sum[i-]+vis[i]; // 求前缀和,sum[i]代表1~的个数和。
}
ll tot=0ll;// 一个数组总的逆序对总和。
repd(i,,n)
{
add(a[i]);
tot+=i-query(a[i]); // quert函数返回的是这个数组中小于等于a[i]的数量
// 那么i-quert 就是 数组中大于a[i]的数量,那么就是逆序对的数量。
// 树状数组 中维护的是一个单点修改,区间查询的树状数组
// 我们add(a[i]) 就是向树状数组中增加一个a[i]出现的次数。
// query(a[i]) 查询的就是 1 ~ a[i] 出现的数量总和。
tot=(tot+mod)%mod;
}
ll ans=tot;
for(int i=;i<=n-;i++)
{
tot=tot-(sum[a[i]-])+n-sum[a[i]];
// -(sum[a[i]-1]) 是减去比a[i]小的个数,即去掉了以a[i]为左的逆序对,
// +n-sum[a[i]]; 是加上 以a[i]为右的逆序对,即加上数组中有多少个数大于a[i]
tot=(tot+mod)%mod;
ans*=tot;
ans=(ans+mod)%mod;
}
cout<<ans<<endl;
return ;
} inline void getInt(int* p) {
char ch;
do {
ch = getchar();
} while (ch == ' ' || ch == '\n');
if (ch == '-') {
*p = -(getchar() - '');
while ((ch = getchar()) >= '' && ch <= '') {
*p = *p * - ch + '';
}
}
else {
*p = ch - '';
while ((ch = getchar()) >= '' && ch <= '') {
*p = *p * + ch - '';
}
}
}

参考了这位大佬的题解:https://blog.csdn.net/qq_40655981/article/details/86547600

 
Maxn   详细X
网络释义
Maxn: 楠楠
int maxN: 乱数产生的最大数字

牛客练习赛38 D 题 出题人的手环 (离散化+树状数组求逆序对+前缀和)的更多相关文章

  1. [NOI导刊2010提高&洛谷P1774]最接近神的人 题解(树状数组求逆序对)

    [NOI导刊2010提高&洛谷P1774]最接近神的人 Description 破解了符文之语,小FF开启了通往地下的道路.当他走到最底层时,发现正前方有一扇巨石门,门上雕刻着一幅古代人进行某 ...

  2. 牛客练习赛33 D tokitsukaze and Inverse Number (树状数组求逆序对,结论)

    链接:https://ac.nowcoder.com/acm/contest/308/D 来源:牛客网 tokitsukaze and Inverse Number 时间限制:C/C++ 1秒,其他语 ...

  3. 牛客练习赛7 E 珂朵莉的数列(树状数组+爆long long解决方法)

    https://www.nowcoder.com/acm/contest/38/E 题意: 思路: 树状数组维护.从大佬那里学习了如何处理爆long long的方法. #include<iost ...

  4. [USACO17FEB] Why Did the Cow Cross the Road I P (树状数组求逆序对 易错题)

    题目大意:给你两个序列,可以序列进行若干次旋转操作(两个都可以转),对两个序列相同权值的地方连边,求最少的交点数 记录某个值在第一个序列的位置,再记录第二个序列中某个值 在第一个序列出现的位置 ,求逆 ...

  5. 牛客练习赛22-E.简单数据结构1(扩展欧拉定理降幂 +树状数组)

    链接:E.简单数据结构1 题意: 给一个长为n的序列,m次操作,每次操作: 1.区间加 2.对于区间,查询 ,一直到- 请注意每次的模数不同.   题解:扩展欧拉定理降幂 对一个数p取log(p)次的 ...

  6. 牛客网多校第5场 H subseq 【树状数组+离散化】

    题目:戳这里 学习博客:戳这里 题意:给n个数为a1~an,找到字典序第k小的序列,输出该序列所有数所在位置. 解题思路:先把所有序列预处理出来,方法是设一个数组为dp,dp[i]表示以i为开头的序列 ...

  7. 牛客网多校第5场 I vcd 【树状数组+离散化处理】【非原创】

    题目:戳这里 学习博客:戳这里 作者:阿狸是狐狸啦 n个点,一个点集S是好的,当且仅当对于他的每个子集T,存在一个右边无限延长的矩形,使的这个矩形包含了T,但是和S-T没有交集. 求有多少个这种集合. ...

  8. cf 61E. Enemy is weak 树状数组求逆序数(WA) 分类: Brush Mode 2014-10-19 15:16 104人阅读 评论(0) 收藏

    #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> ...

  9. 出题人的手环(牛客练习赛38D 离散化+树状数组)

    题目链接(https://ac.nowcoder.com/acm/contest/358/D) 题目描述 出题人的妹子送了出题人一个手环,这个手环上有 n 个珠子,每个珠子上有一个数. 有一天,出题人 ...

随机推荐

  1. MySQL并行复制的一个坑

    早上巡检数据库,发现一个延迟从库的sql_thread中断了. Last_SQL_Errno: 1755 Last_SQL_Error: Cannot execute the current even ...

  2. 将web项目部署到阿里云服务器上

    一.用eclipse将写好的项目打成war包 1.右键点击项目,选择Export 选择打包之后的路径,点击Finsh. 2.购买阿里云服务器 按下图选择 3.设置云服务器防火墙 4.远程连接云服务器 ...

  3. Amazon onsite behavior question

    https://www.1point3acres.com/bbs/thread-307462-1-1.html http://kraftshala.com/how-to-raise-the-bar-i ...

  4. The host '192.168.174.130' is unreachable. the host may be down..............

    The host '192.168.174.130' is unreachable.      the host may be down,or there may be a problem with ...

  5. LeetCode算法题-First Unique Character in a String(Java实现)

    这是悦乐书的第213次更新,第226篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第81题(顺位题号是387).给定一个字符串,找到它中的第一个非重复字符并返回它的索引. ...

  6. 【2018.04.27 C与C++基础】关于switch-case及if-else的效率问题

    对于这个问题自己是比较清楚的,在分支比较多时,switch-case的效率肯定比if-else的要高许多,其原理类似于我们在优化某些程序时使用查表来代替算法计算一样. 如果想进一步深究的话,可以查看G ...

  7. March 05th, 2018 Week 10th Monday

    Fortune favors the bold. 勇者天佑. It has been increasingly apparent that courage is the main quality we ...

  8. Docker: dockerfile常用关键字

    Dockerfile指令 Dockfile执行和shell命令一行,一行一行执行- 写Dockerfile注意点: 1.           尽量少RUN 2.           多个命令拼接在一起 ...

  9. html + js 实现图片上传,压缩,预览及图片压缩后得到Blob对象继续上传问题

    先上效果 上传图片后(设置了最多上传3张图片,三张后上传按钮消失) 点击图片放大,可以使用删除和旋转按钮 (旋转功能主要是因为ios手机拍照后上传会有写图片被自动旋转,通过旋转功能可以调正) html ...

  10. BSOJ 5603 -- 【SNOI2017】炸弹

    题好数据水系列,网上的十几行神仙解法A了原数据. 这道题要用到线段数优化建图的知识.然而考试考到这道题时我还不会. 我们设分别表示每个炸弹向左和向右最远能炸到哪个炸弹.很容易想到一个思路,就是每个炸弹 ...