poj 3378 二维树状数组
思路:直接用long long 保存会WA。用下高精度加法就行了。
#include<map> #include<set> #include<cmath> #include<queue> #include<cstdio> #include<vector> #include<string> #include<iomanip> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define pb push_back #define mp make_pair #define Maxn 50010 #define Maxm 80002 #define LL __int64 #define Abs(x) ((x)>0?(x):(-x)) #define lson(x) (x<<1) #define rson(x) (x<<1|1) #define inf 100000 #define lowbit(x) (x&(-x)) #define mod 1000000000 using namespace std; LL c[Maxn][5][2]; int n,num[Maxn]; struct OO{ LL val[2]; }; struct PP{ int val,i; int operator<(const PP &temp) const{ return val<temp.val; } }sorted[Maxn]; void update(int pos,int num,OO temp) { while(pos<=n){ c[pos][num][0]+=temp.val[0]; c[pos][num][1]+=temp.val[1]; c[pos][num][1]+=c[pos][num][0]/mod; c[pos][num][0]%=mod; pos+=lowbit(pos); } } OO Sum(int pos,int num) { OO sum; sum.val[0]=sum.val[1]=0; while(pos){ sum.val[0]+=c[pos][num][0]; sum.val[1]+=c[pos][num][1]; sum.val[1]+=sum.val[0]/mod; sum.val[0]%=mod; pos-=lowbit(pos); } return sum; } int main() { int i,j; //freopen("ttt.txt","r",stdin); while(scanf("%d",&n)!=EOF){ memset(c,0,sizeof(c)); for(i=1;i<=n;i++){ scanf("%d",num+i); sorted[i].val=num[i]; sorted[i].i=i; } sort(sorted+1,sorted+1+n); int cnt=0; for(i=1;i<=n;i++){ if(sorted[i].val!=sorted[i-1].val){ num[sorted[i].i]=++cnt; } else num[sorted[i].i]=cnt; } OO sum; sum.val[0]=sum.val[1]=0; OO temp; for(i=1;i<=n;i++){ temp=Sum(num[i]-1,4); sum.val[0]+=temp.val[0]; sum.val[1]+=temp.val[1]; sum.val[1]+=sum.val[0]/mod; sum.val[0]%=mod; temp.val[0]=1; temp.val[1]=0; update(num[i],1,temp); for(j=4;j>=2;j--) update(num[i],j,Sum(num[i]-1,j-1)); } if(sum.val[1]){ printf("%I64d",sum.val[1]); cout<<right<<setw(9)<<setfill('0')<<sum.val[0]<<endl; } else printf("%I64d\n",sum.val[0]); } return 0; }