(双方向)逆転しようとしているch4201楼蘭トーテムフェンウィックツリー

説明

割り当てられたタスクを完了した後、西は、楼蘭の古代都市の314西に来ました。伝説によると、昔、この土地に(それ以前楼蘭の古代都市よりは)2つの部族、部族の崇拝ナイフ(「V」)、部族の礼拝スペード(「∧」)を住んでいた、と彼らが表現するためにV字状とした∧それぞれの部族のトーテム。
以下Kroraina 314にウエスト巨大壁画を発見し、点Nと垂直位置の水平方向の位置を測定することにより求めた点Nを、標識された壁画は、ペアワイズ互いに素です。西情報は、N点の相対位置と壁画に含まれているので、我々は、座標(1、Y1)であると仮定することができること314、(2 、Y 2)、...、(N、YN)、 Y1〜YN nは1が配置されています。

次のように西314はVが定義され、壁画はトーテムを含有するどのように多くのトーテムを検査しようとする(注:のみトーテムの形態と約3縦の順序の相対的な大きさ)1 <= iの= <K <Jが< n及びYI> YJ、YJ <YK。

礼拝∧部族トーテムのように定義されている1 <= iが<jの<K <= N及びYI <YJ、YJ> YK。

314西は2つの部族のトーテムにn個の点の数を知りたいです。そのため、あなたは数および∧Vの数を見つけるためのプログラムを記述する必要があります。

入力形式

n個の第一行
2行目のは、数あるN、Y1、Y2を表す...... YN

出力フォーマット

2つの数字が
スペースで区切っ
Vと番号の数字が続き∧

サンプル入力

5
1 5 3 2 4

サンプル出力

3 4

データ範囲と表記

データ・N- <600 = 10%の
データのN- <5000 = 40%
、100%のデータN <= 200000は、答えがInt64型を超えていない\

分析:

まず、後戻りすることはフェンウィックツリーで逆転しようとします:ここで
前方得スキャン左に現在のポイントよりも大きなポイントを [i]を左数の
(まだ現在のポイント・ポイントよりも小さい数)
逆スキャンは、一度取得しました現在の点と右点より右側[i]の数である
(と現在のポイントよりも少ないドット数)
、その後の各点列挙されている
* [I]需要が左= + V字形ANSで右[i]は
別の同様の
コンクリートコードを見て

PS:
後ろ最初のいくつかのケースはWAされた後
、最後の検出プロセスがintの乗算を破裂されます、私はショックを受けた、良いことではない答えがint超えないでください
あなたが密接に見れない、それはint64型以上のものではありません。それは長い長い、です。有毒

コード:

#include<iostream>
#include<cstdio>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=2e5+5;
int a[maxm];
int c[maxm];
int n;
int l[maxm];
int r[maxm];
int l2[maxm];
int r2[maxm];
int lowbit(int x){
    return x&(-x);
}
void add(int i,int t){
    while(i<maxm){
        c[i]+=t;
        i+=lowbit(i);
    }
}
int sum(int i){
    int res=0;
    while(i){
        res+=c[i];
        i-=lowbit(i);
    }
    return res;
}
int main(){
    while(cin>>n){
        memset(c,0,sizeof c);
        for(int i=1;i<=n;i++){
            cin>>a[i];
            add(a[i],1);
            l[i]=i-sum(a[i]);//求左边比他大的点 的数量
            l2[i]=sum(a[i]-1);//求左边比他小的 的数量
        }
        memset(c,0,sizeof c);
        for(int i=n;i>=1;i--){
            add(a[i],1);
            r[i]=(n-i+1)-sum(a[i]);//求右边比他大的点 的数量
            r2[i]=sum(a[i]-1);//求右边比他小的点 的数量
        }
        ll ans1=0,ans2=0;
        for(int i=1;i<=n;i++){
            ans1+=(long long)l[i]*r[i];//这里乘法爆int,贼坑
            ans2+=(long long)l2[i]*r2[i];
        }
        cout<<ans1<<' '<<ans2<<endl;
    }
    return 0;
}

おすすめ

転載: blog.csdn.net/weixin_44178736/article/details/92019875