Time Limit: 3000MS | Memory Limit: 65536K | |
Total Submissions: 6092 | Accepted: 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
#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][n]+=delta;
c[cur][n]=add(c[cur][n],delta);
n+=low_bit(n);
}
}
bign sum(int n,int cur)
{
bign s;
s.init();
while(n!=0)
{
//s+=c[cur][n];
s=add(s,c[cur][n]);
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,无语.
有时间再改.