求得XYZ,XZY 再求得XYZ,然后相减即答案 = =。。脑子笨死了,赛场卡在第5题了,这题没怎么想。
求XYZ,XZY只需求X后有多少个比它大的,求下C(n,2)
求XYZ求 Y前面有比它小的后面比它大的数,两个数乘下。
昨晚用线段树了,擦边过。。时间好长。今早试了下树状数组,才跑了100+MS。。。这差距。。
线段树
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define FOR(i,s,t) for(int i=s; i<t; i++)
#define BUG puts("here!!!")
using namespace std;
const int MAX = 100010;
struct Tnode{ // 一维线段树
int l,r,sum;
int len() { return r - l;}
int mid() { return MID(l,r);}
bool in(int ll,int rr) { return l >= ll && r <= rr; }
void lr(int ll,int rr){ l = ll; r = rr;}
};
Tnode node[MAX<<2];
int a[MAX];
void Updata_sum(int t)
{
node[t].sum = node[L(t)].sum + node[R(t)].sum;
}
void Build(int t,int l,int r)
{
node[t].lr(l,r);
if( node[t].len() == 1 )
{
node[t].sum = 0;
return ;
}
int mid = MID(l,r);
Build(L(t),l,mid);
Build(R(t),mid,r);
Updata_sum(t);
}
void Updata(int t,int l,int r,int val)
{
if( node[t].in(l,r) )
{
node[t].sum = val;
return ;
}
if( node[t].len() == 1 ) return ;
int mid = node[t].mid();
if( l < mid ) Updata(L(t),l,r,val);
if( r > mid ) Updata(R(t),l,r,val);
Updata_sum(t);
}
int Query(int t,int l,int r)
{
if( node[t].in(l,r) ) return node[t].sum;
if( node[t].len() == 1 ) return 0;
int mid = node[t].mid();
int ans = 0;
if( l < mid ) ans += Query(L(t),l,r);
if( r > mid ) ans += Query(R(t),l,r);
return ans;
}
int main()
{
int ncases, n, ind = 1;
scanf("%d", &ncases);
while( ncases-- )
{
scanf("%d", &n);
Build(1, 0, n+1);
for(int i=0; i<n; i++)
scanf("%d", &a[i]);
__int64 ans = 0, sum = 0;
Build(1, 0, n+1);
for(int i=0; i<n; i++)
{
int p = Query(1, 0, a[i]);
sum += (n - i + p - a[i])*1ll*p;
ans += (n - i + p - a[i])*1ll*(n - i + p - a[i] - 1)/2;
Updata(1, a[i]-1, a[i], 1);
}
printf("Case #%d: %I64d\n", ind++, (ans - sum)%100000007);
}
return 0;
}
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define FOR(i,s,t) for(int i=s; i<t; i++)
#define BUG puts("here!!!")
using namespace std;
const int MAX = 100010;
int c[MAX];
int Lowbit(int x)
{
return x & (-x);
}
void Updata(int x,int num)// num 可能都为1,具体问题具体分析
{
int i;
for(i=x; i<MAX; i+=Lowbit(i))
c[i] += num; // 若num 为1,c[i]++
}
int Getsum(int x)//sum的返回值的类型可能是long long ,根据题意判断
{
int sum = 0,i;
for(i=x; i>0; i-=Lowbit(i))
sum += c[i];
return sum;
}
int a[MAX];
int main()
{
int ncases, n, ind = 1;
scanf("%d", &ncases);
while( ncases-- )
{
scanf("%d", &n);
memset(c, 0, sizeof(c));
for(int i=0; i<n; i++)
scanf("%d", &a[i]);
__int64 ans = 0, sum = 0;
for(int i=0; i<n; i++)
{
int p = Getsum(a[i]);
sum += (n - i + p - a[i])*1ll*p;
ans += (n - i + p - a[i])*1ll*(n - i + p - a[i] - 1)/2;
Updata(a[i], 1);
}
printf("Case #%d: %I64d\n", ind++, (ans - sum)%100000007);
}
return 0;
}