NOIP一模DAY 1爆炸记

由于本蒟蒻太弱了,再加上刚开学心态没调整好,day 1直接炸穿,模拟都没写出来qwq。

在此只是更新一下题解
T1 自己找个骰子模拟;
T2 很显然我们要枚举数列每个元素i,求1到i-1、i+1到n 中比它大的数的个数和比它小的数的个数,朴素的方法是N^2的,我们需要优化,我们可以先离散化,建一课1到n的树状数组(代表某个值域中出现了几个数),每次枚举一个点时,log n查询,查询完后单点修改,复杂度nlogn;

#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=200006;
const long long mod=1e9+7;
int n;
int c[maxn*2];
inline void update (int wh,int x)
{
	for (int i=wh;i<=n;i+=(i&-i)) c[i]+=x;
}
inline int query (int wh)
{
	int ans=0;
	for (int i=wh;i>0;i-=(i&-i))
	{
		ans+=c[i];
	}
	return ans;
}
long long  litt1[maxn],litt2[maxn],big1[maxn],big2[maxn];
struct hzw
{
	int v;
	int rv;
	int id;
}t[maxn];
bool cmp(hzw a,hzw b)
{
	return a.rv<b.rv;
}
bool cmp2(hzw a,hzw b)
{
	return a.id<b.id;
}
int main()
{
	freopen("sub.in","r",stdin);
	freopen("sub.out","w",stdout);
	cin>>n;
	for (int i=1;i<=n;++i)
	{
		scanf("%d",&t[i].rv);
		t[i].id=i;
	}
	sort(t+1,t+1+n,cmp);
	int tot=0;
	for (int i=1;i<=n;++i)
	{
	
		if (t[i].rv!=t[i-1].rv) 
		{
			t[i].v=++tot;
		}
		else t[i].v=t[i-1].v;	
	}
	sort(t+1,t+1+n,cmp2);
	for (int i=1;i<=n;++i)
	{
		litt1[i]=query(t[i].v-1);
		big1[i]=query(n)-query(t[i].v);
		update(t[i].v,1);
	}
	memset(c,0,sizeof(c));
	for (int i=n;i>=1;i--)
	{
		litt2[i]=query(t[i].v-1);
		big2[i]=query(n)-query(t[i].v);
		update(t[i].v,1);
	}
	long long ans=0;
	for (int i=1;i<=n;++i)
	{
		ans=(ans+(big1[i]*litt2[i])%mod+(big2[i]*litt1[i])%mod)%mod;
	}
	cout<<ans;
	return 0;
}

posted @ 2018-08-25 15:40  Splitor  阅读(147)  评论(0编辑  收藏  举报