题目大意:
一个数列,求i,j,k,l,m满足: 1 ≤ i < j < k < l < m ≤ N 且 Ai < Aj < Ak < Al < Am
有几组不同的i,j,k,l,m
思路:
显而易见是:四个树状数组搞定
但是看了一眼数据量:(1 ≤ N ≤ 50000) ,每个数不超过109
这就很恶心,需要高精度(还是压位!!!)和离散化
然后就是写完上述两个小技巧再加上树状数组的正经代码
PS:小技巧比正经的树状数组难写到不知道哪里去了,小技巧调了有5个多小时 TAT,果然还是太菜了
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<cstdlib> #include<vector> #include<queue> #define ll long long #define inf 2147483611 #define MAXN 101010 #define mod 1000000000 using namespace std; inline ll read() { ll x=0,f=1; char ch;ch=getchar(); while(!isdigit(ch)) {if(ch==‘-‘) f=-1;ch=getchar();} while(isdigit(ch)) {x=x*10+ch-‘0‘;ch=getchar();} return x*f; } struct bign { ll num[100],len; bign() { memset(num,0,sizeof(num)); len=0; } void clear() { memset(num,0,sizeof(num)); len=0; } void plusn(ll b) { ll cnt=0; while(b) num[cnt++]+=b%mod,b/=mod; for (ll i=0;i<len;i++) num[i+1]+=num[i]/mod,num[i]%=mod; while(num[len]>=mod) num[len+1]+=num[len]/mod,num[len]%=mod,len++; } void printn() { printf("%lld",num[len]); for(int i=len-1;i>=0;i--) { printf("%09lld",num[i]); } printf("\n"); } }ans; ll n,g[MAXN]; ll c[6][MAXN]; struct ar { ll val,pos; ar(){val=pos=0;} }a[MAXN]; bool cmp1(ar t,ar r) {return t.val<r.val;} ll lowbit(ll x) {return x&(-x);} void add(ll x,ll i,ll v) {while(i<=MAXN) {c[x][i]+=v;i+=lowbit(i);}} ll sum(ll x,ll i) { ll ans=0; while(i) { ans+=c[x][i]; i-=lowbit(i); } return ans; } int main() { //freopen("a.in","r",stdin); //freopen("a.out","w",stdout); ll k; while((scanf("%lld",&n))!=EOF) { for(ll i=1;i<=n;i++) {a[i].val=read();a[i].pos=i;} sort(a+1,a+n+1,cmp1); ll cnt=1; for(ll i=1;i<=n;i++) {g[a[i].pos]=cnt;if(a[i].val!=a[i+1].val) cnt++;} ans.clear(); memset(c,0,sizeof(c)); for(ll i=1;i<=n;i++) { ll k=1; add(0,g[i],k); if(g[i]==1) continue; for(int j=1;j<=4;j++) { k=sum(j-1,g[i]-1); add(j,g[i],k); } ans.plusn(k); } ans.printn(); } }
时间: 2024-10-04 20:09:08