您的位置:首页 > 大数据 > 人工智能

POJ3378:Crazy Thairs(动态规划+线段树或树状数组+离散化+高精度)

2012-11-28 22:19 363 查看
Crazy Thairs

Time Limit: 3000MSMemory Limit: 65536K
Total Submissions: 6092Accepted: 1478
Description

These days, Sempr is crazed on one problem named Crazy Thair. Given N (1 ≤ N ≤ 50000) numbers, which are no more than 109, Crazy Thair is a group of 5 numbers {i, j, k, l, m}
satisfying:

1. 1 ≤ i < j < k < l < m ≤ N

2. Ai < Aj < Ak < Al < Am

For example, in the sequence {2, 1, 3, 4, 5, 7, 6},there are four Crazy Thair groups: {1, 3, 4, 5, 6}, {2, 3, 4, 5, 6}, {1, 3, 4, 5, 7} and {2, 3, 4, 5, 7}.

Could you help Sempr to count how many Crazy Thairs in the sequence?

Input

Input contains several test cases. Each test case begins with a line containing a number N, followed by a line containing N numbers.

Output

Output the amount of Crazy Thairs in each sequence.

Sample Input

5
1 2 3 4 5
7
2 1 3 4 5 7 6
7
1 2 3 4 5 6 7

Sample Output

1
4
21

Source

POJ Monthly--2007.09.09, tdzl2003
MYCode:

#include<iostream>

#include<cstring>

#include<cstdio>

#include<algorithm>

using namespace std;

#define MAX 50010

int list[MAX];

int st[MAX];

struct bign

{

char m[30];//note

int len;

void init()

{

memset(m,0,sizeof(m));

len=1;//note

}

};

bign add(bign aa,bign bb)

{

bign c;

c.init();

int len=aa.len>bb.len?aa.len:bb.len;

int i;

c.len=len;

for(i=0;i<len;i++)

{

c.m[i]+=aa.m[i]+bb.m[i];

if(c.m[i]>=10)

{

c.m[i+1]+=c.m[i]/10;

c.m[i]%=10;

if(i+2>len)

c.len=i+2;

}

}

return c;

}

struct node

{

int lt;

int rt;

bign v;

}a[6][4*MAX];

int v[MAX];

bign num[6];

int ct;

void build(int s,int t,int step,int cur)

{

a[cur][step].lt=s;

a[cur][step].rt=t;

//a[cur][step].v=0;

a[cur][step].v.init();//note

if(a[cur][step].lt==a[cur][step].rt)

return;

int mid=(s+t)/2;

build(s,mid,2*step,cur);

build(mid+1,t,2*step+1,cur);

}

void modify(int s,int t,int step,bign val,int cur)

{

if(a[cur][step].lt==s && a[cur][step].rt==t)

{

//a[cur][step].v+=val;

a[cur][step].v=add(a[cur][step].v,val);

return;

}

if(a[cur][step].lt==a[cur][step].rt)return;

int mid=(a[cur][step].lt+a[cur][step].rt)/2;

if(t<=mid)

modify(s,t,2*step,val,cur);

else

modify(s,t,2*step+1,val,cur);

//a[cur][step].v=a[cur][2*step].v+a[cur][2*step+1].v;

a[cur][step].v=add(a[cur][2*step].v,a[cur][2*step+1].v);

}

bign query(int s,int t,int step,int cur)

{

if(a[cur][step].lt==s&&a[cur][step].rt==t)

{

return a[cur][step].v;

}

if(a[cur][step].lt==a[cur][step].rt)return a[cur][step].v;

int mid=(a[cur][step].lt+a[cur][step].rt)/2;

if(t<=mid)

return query(s,t,2*step,cur);

else if(mid<s)

return query(s,t,2*step+1,cur);

else

{

return add(query(s,mid,2*step,cur),query(mid+1,t,2*step+1,cur));

}

}

int search(int val)

{

int lt=1,rt=ct;

while(lt<=rt)

{

int mid=(lt+rt)/2;

if(list[mid]==val)

return mid;

if(list[mid]<val)

lt=mid+1;

else

rt=mid-1;

}

return -1;

}

int main()

{

int n;

while(scanf("%d",&n)!=EOF)

{

memset(a,0,sizeof(a));

int i,j;

//int most=-1;//note

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

{

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

st[i]=v[i];

//if(v[i]>most)

//most=v[i];

}

sort(st+1,st+n+1);

ct=1;

list[1]=st[1];

for(i=2;i<=n;i++)

{

if(st[i]!=st[i-1])

{

list[++ct]=st[i];

}

}

for(i=1;i<=5;i++)

build(1,ct,1,i);

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

{

//memset(num,0,sizeof(num));

for(j=1;j<=4;j++)

num[j].init();

int id=search(v[i]);

if(id>=2)

{

for(j=1;j<=4;j++)

{

num[j]=query(1,id-1,1,j);

}

}

bign tp;

tp.m[0]=1;

tp.len=1;//note

modify(id,id,1,tp,1);

for(j=1;j<=4;j++)

{

if(num[j].len!=1||num[j].len==1&&num[j].m[0]!=0)

modify(id,id,1,num[j],j+1);

}

}

bign ans=query(1,ct,1,5);

//printf("%d\n",ans);

int len=ans.len;

for(i=len-1;i>=0;i--)

{

printf("%d",ans.m[i]);

}

printf("\n");

}

}

//未通过.

动态规划+线段树+离散化+高精度计算

MYCode:(树状数组版本,TLE)

#include<iostream>

#include<cstring>

#include<cstdio>

#include<algorithm>

using namespace std;

#define MAX 50010

int list[MAX];

int st[MAX];

struct bign

{

char m[50];//note

int len;

void init()

{

memset(m,0,sizeof(m));

len=1;//note

}

};

bign add(bign aa,bign bb)

{

bign c;

c.init();

int len=aa.len>bb.len?aa.len:bb.len;

int i;

c.len=len;

for(i=0;i<len;i++)

{

c.m[i]+=aa.m[i]+bb.m[i];

if(c.m[i]>=10)

{

c.m[i+1]+=c.m[i]/10;

c.m[i]%=10;

if(i+2>len)

c.len=i+2;

}

}

return c;

}

int v[MAX];

bign num[6];

int ct;

bign c[6][MAX];

int low_bit(int x)

{

return x&(-x);

}

void modify(int n,bign delta,int cur)

{

while(n<=ct)

{

//c[cur]
+=delta;

c[cur]
=add(c[cur]
,delta);

n+=low_bit(n);

}

}

bign sum(int n,int cur)

{

bign s;

s.init();

while(n!=0)

{

//s+=c[cur]
;

s=add(s,c[cur]
);

n-=low_bit(n);

}

return s;

}

int search(int val)

{

int lt=1,rt=ct;

while(lt<=rt)

{

int mid=(lt+rt)/2;

if(list[mid]==val)

return mid;

if(list[mid]<val)

lt=mid+1;

else

rt=mid-1;

}

return -1;

}

int main()

{

int n;

while(scanf("%d",&n)!=EOF)

{

memset(c,0,sizeof(c));

int i,j;

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

{

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

st[i]=v[i];

}

sort(st+1,st+n+1);

ct=1;

list[1]=st[1];

for(i=2;i<=n;i++)

{

if(st[i]!=st[i-1])

{

list[++ct]=st[i];

}

}

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

{

//memset(num,0,sizeof(num));

//for(j=1;j<=4;j++)

//num[j].init();

int id=search(v[i]);

for(j=1;j<=4;j++)

{

num[j]=sum(id-1,j);

}

bign tp;

tp.m[0]=1;

tp.len=1;//note

modify(id,tp,1);

for(j=1;j<=4;j++)

{

modify(id,num[j],j+1);

}

}

bign ans=sum(ct,5);

//printf("%d\n",ans);

int len=ans.len;

for(i=len-1;i>=0;i--)

{

printf("%d",ans.m[i]);

}

printf("\n");

}

}

//TLE

数据范围大,所以要离散化

答案大,所以要高精度

各种TLE,MLE,RE.

用线段树或者是树状数组优化竟然还TLE,无语.

有时间再改.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: