题目https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=26&problem=2330&mosmsg=Submission+received+with+ID+1779597
题意:
一条大街上住着n个乒乓球爱好者,经常组织比赛切磋技术。每个人都有一个能力值a[i]。每场比赛需要三个人:两名选手,一名裁判。他们有个奇怪的约
定,裁判必须住在两名选手之间,而裁判的能力值也必须在两名选手之间。问一共能组织多少种比赛。
枚举2-n-1 ai为裁判时, 假设a1~a(i-1)中有ci个比ai小的数, a(i+1)~an中有di个比ai小的数
那么比赛次数 为 ci*(n-i-di) + (i-1-ci)*di
所以把2~n-1的情况都枚举求和就好了
两种做法求ci:
第一种排名树:
对于求ci..我是用treap实现的排名树来求得:
开两个treap, treap1先储存好a1~an
然后把a1插入treap2
for (i=2;i<=n;i++)
{
把ai插入treap2,求出treap2中 ai的排名 ,显然 排名减1就是比ai小的数的个数,也就是我们要求的ci (a1~a(i-1)中比ai小的数的个数)
再在treap1中求ai的排名,显然排名减1得到的是所有比ai小的数的个数,再减去ci,便得到di ( a(i+1)~an中比ai小的数的个数 )
}
for里面每次操作是logn的,因此复杂度也就是nlogn
后来试着用int交了一下是wa。。必须longlong ,LA不支持int64
-
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
#include <iostream>
using namespace std;
#define MAXN 20005
struct data{
long long l,r,v,size,rnd,w;
};
class tp
{
public:
long long n,size,root,ans;
tp()
{
n=size=root=ans=0;
}
data tr[MAXN];
void update(long long k)//更新结点信息
{
tr[k].size=tr[tr[k].l].size+tr[tr[k].r].size+tr[k].w;
}
void rturn(long long &k)
{
long long t=tr[k].l;tr[k].l=tr[t].r;tr[t].r=k;
tr[t].size=tr[k].size;update(k);k=t;
}
void lturn(long long &k)
{
long long t=tr[k].r;tr[k].r=tr[t].l;tr[t].l=k;
tr[t].size=tr[k].size;update(k);k=t;
}
void insert(long long &k,long long x)
{
if(k==0)
{
size++;k=size;
tr[k].size=tr[k].w=1;tr[k].v=x;tr[k].rnd=rand();
return;
}
tr[k].size++;
if(tr[k].v==x)tr[k].w++;//每个结点顺便记录下与该节点相同值的数的个数
else if(x>tr[k].v)
{
insert(tr[k].r,x);
if(tr[tr[k].r].rnd<tr[k].rnd)lturn(k);//维护堆性质
}
else
{
insert(tr[k].l,x);
if(tr[tr[k].l].rnd<tr[k].rnd)rturn(k);
}
}
long long query_rank(long long k,long long x)
{
if(k==0)return 0;
if(tr[k].v==x)return tr[tr[k].l].size+1;
else if(x>tr[k].v)
return tr[tr[k].l].size+tr[k].w+query_rank(tr[k].r,x);
else return query_rank(tr[k].l,x);
}
};
tp sp;
tp sp2;
long long tm[MAXN];
long long c[MAXN],d[MAXN];
int main()
{
long long t;
scanf("%lld",&t);
while (t--)
{
long long n;
memset(sp.tr,0,sizeof(sp.tr));
memset(sp2.tr,0,sizeof(sp2.tr));
sp.n=sp.size=sp.root=sp.ans=0;
sp2.n=sp2.size=sp2.root=sp2.ans=0;
scanf("%lld",&n);
long long i;
for( i = 1; i <= n; i++)
{
scanf("%lld",&tm[i]);
sp.insert(sp.root,tm[i]);
}
sp2.insert(sp2.root,tm[1]);
for( i = 2; i <= n; i++)
{
sp2.insert(sp2.root,tm[i]);
long long tmp=sp2.query_rank(sp2.root,tm[i]);
c[i]=tmp-1;
tmp=sp.query_rank(sp.root,tm[i]);
d[i]=tmp-1-c[i];
}
long long sum=0;
for (i=2;i<=n-1;i++)
{
sum+=c[i]*(n-i-d[i])+d[i]*(i-1-c[i]);
}
printf("%lld\n",sum);
}
return 0;
}
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
#include <iostream>
using namespace std;
#define MAXN 20005
const int up=100005;
int tm[MAXN];
int c[MAXN],d[MAXN];
int tree[up];
int lowbit(int x)
{
return x&-x;
}
void add(int x,int value)
{
for (int i=x;i<=up;i=i+lowbit(i))
{
tree[i]+=value;
}
}
int get(int x)
{
int sum=0;
for (int i=x;i;i-=lowbit(i))
{
sum+=tree[i];
}
return sum;
}
int main()
{
int t;
scanf("%d",&t);
while (t--)
{
int n;
scanf("%d",&n);
int i;
for( i = 1; i <= n; i++)
{
scanf("%d",&tm[i]);
}
memset(tree,0,sizeof(tree));
for( i = 1; i <= n; i++)
{
add(tm[i],1);
c[i]=get(tm[i]-1);
}
memset(tree,0,sizeof(tree));
for( i = n; i>=1; i--)
{
add(tm[i],1);
d[i]=get(tm[i]-1);
}
long long sum=0;
for (i=2;i<=n-1;i++)
{
sum+=c[i]*(n-i-d[i])+d[i]*(i-1-c[i]);
}
printf("%lld\n",sum);
}
return 0;
}