1 条题解
-
0yejun LV 10 MOD @ 2019-01-08 21:04:00
/* 树状数组模板题 由于所有数字互不相同,且为1~n的排列,所以可以运用了树状数组的一个功能 查找每个数左侧比它小的数字的个数 for(int i=1;i<=n;i++){ l1[i]=sum(a[i]); add(a[i]); } 将数组颠倒过来,就能够求每个数右边比它小的数的个数(逆序扫描数组也可以) 于是枚举中间点,统计左右比它小数的个数相乘,即可得到以这个数字为中心的一种形状的个数 对于另一个形状,只要将数组倒过来,即令a[i]=n-a[i]即可 */ #define method_1 #ifdef method_1 /* */ #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<set> #include<map> #include<queue> #include<stack> #include<vector> #include<cstring> #include<cstdlib> using namespace std; typedef long long ll; const int maxn=200000+5; const int INF=0x3f3f3f3f; ll n,a[maxn],c[maxn],l1[maxn],l2[maxn],r1[maxn],r2[maxn],ans1=0,ans2=0; void add(ll x){ for(int i=x;i<=n;i+=i&-i){ c[i]++; } } ll sum(ll x){ ll sum=0; for(int i=x;i>0;i-=i&-i){ sum+=c[i]; } return sum; } int main() { ios::sync_with_stdio(false); cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; a[i]=n-a[i]+1; } memset(c,0,sizeof(c)); for(int i=1;i<=n;i++){ l1[i]=sum(a[i]); add(a[i]); } memset(c,0,sizeof(c)); for(int i=n;i>=1;i--){ r1[i]=sum(a[i]); add(a[i]); } for(int i=1;i<=n;i++){ // cout<<l1[i]<<" "<<r1[i]<<endl; ans1+=l1[i]*r1[i]; } cout<<ans1<<" "; for(int i=1;i<=n;i++){ a[i]=n-a[i]+1; } memset(c,0,sizeof(c)); for(int i=1;i<=n;i++){ l2[i]=sum(a[i]); add(a[i]); } memset(c,0,sizeof(c)); for(int i=n;i>=1;i--){ r2[i]=sum(a[i]); add(a[i]); } for(int i=1;i<=n;i++){ // cout<<l2[i]<<" "<<r2[i]<<endl; ans2+=l2[i]*r2[i]; } cout<<ans2; return 0; } #endif #ifdef method_2 /* */ #endif #ifdef method_3 /* */ #endif
- 1
信息
- 难度
- 5
- 分类
- (无)
- 标签
- (无)
- 递交数
- 37
- 已通过
- 15
- 通过率
- 41%
- 被复制
- 3
- 上传者