HDU 5792 World is Exploding

题意:

给出n代表序列的长度,接下来给出序列A。找出abcd满足abcd互不相等1<=a<b<c<d<=n的同时A[a]<A[b],A[c]>A[d],问这样的abcd有几个.

思路:先忽略四个数两两不相等的条件,那就是(,逆序对个数)乘上(顺序对个数)。例如{2,4,1,3},逆序对就是{(2,1),(4,1),(4,3)} ,顺序对就是{(2,4),(2,3),(1,3)},这样3*3=9,一共九个符合a<b && c>d的四元组。但其中有很多不合法的,对于t这个数,不合法情况的个数就是 (关于t的逆序对个数×关于t的顺序对个数),一一减去就是结果了。(不合法的规律多写几组便能找到)

输入:

4

2 4 1 3

4

1 2 3 4

输出:

1
0

代码:

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cmath>

#include <vector>

#include <queue>

#include <cstring>

#include <string>

#include <algorithm>

using namespace std;

typedef  long long  ll;

typedef unsigned long long ull;

#define MM(a,b) memset(a,b,sizeof(a));

#define inf 0x7f7f7f7f

#define FOR(i,n) for(int i=1;i<=n;i++)

#define CT continue;

#define PF printf

#define SC scanf

const int mod=1000000007;

const int N=1e6+10;

int tmp[N],a[N],n,m,c[N],pos[N];

ll lmin[N],rmin[N],lmax[N],rmax[N];

int lowbit(int i)

{

return i&(-i);

}

void add(int x)

{

while(x<=m)

{

c[x]+=1;

x+=lowbit(x);

}

}

int query(int x)

{

int res=0;

while(x>0)

{

res+=c[x];

x-=lowbit(x);

}

return res;

}

int main()

{

while(~scanf("%d",&n))

{

for(int i=1;i<=n;i++)

{

scanf("%d",&tmp[i]);

a[i]=tmp[i];

}

sort(tmp+1,tmp+n+1);//将tmp按从小到大排序,用于树状数组查找顺/逆序对

m=unique(tmp+1,tmp+n+1)-tmp-1;//去重

for(int i=1;i<=n;i++)

pos[i]=lower_bound(tmp+1,tmp+m+1,a[i])-tmp;//找到原来的第i个数在排序后应在的位置

MM(c,0);

for(int i=1;i<=n;i++)//查询0-i-1之间比a[i]小的数放在lmin[i]里,在i-m之间比a[i]大的放在lmax里

{

lmin[i]=query(pos[i]-1);//

lmax[i]=query(m)-query(pos[i]);

add(pos[i]);

}

MM(c,0);

for(int i=n;i>=1;i--)//逆着再来一次

{

rmin[i]=query(pos[i]-1);

rmax[i]=query(m)-query(pos[i]);

add(pos[i]);

}

ll ans=0,l=0,r=0;

for(int i=1;i<=n;i++)  {r+=rmax[i],l+=lmax[i];};

ans=l*r;

for(int i=1;i<=n;i++)//去除不合法的

{

ans-=lmin[i]*rmin[i];

ans-=lmax[i]*rmax[i];

ans-=lmax[i]*lmin[i];

ans-=rmax[i]*rmin[i];

}

printf("%lld\n",ans);

}

return 0;

}

上一篇:添加/删除 windows下Git右键菜单


下一篇:Android 手机卫士10--应用管理器