power oj 2840: 伯陵防線 思維+樹狀數組

2840: 伯陵防線

Time Limit: 1000 MS Memory Limit: 262144 KB
Total Submit: 9 Accepted: -4 Page View: 81
Submit Status Discuss

Description

爲抵禦巫妖王——阿爾薩斯·米奈希爾的入侵,Wangshu

在洛蘭深處的召喚師峽谷一側設立了一道伯陵防線。

這道防線從南到北依次排開,每隔一定的距離就有一個防禦點,每個防禦點由草薙京防守,而每個防禦點都可能裝備着 M4A1,M4A1−S,AK47 等很多種槍的一種,

所以每個防禦點也有不同的防禦範圍(防禦點爲圓心的圓),要痛擊敵人就得先保存自己的實力。

我們定義兩個防禦點a,b,滿足 b 在 a 的防禦範圍內,且 a 在 b 的防禦範圍內,即 a b

可以相互保護,我們就認爲他們是華農兄弟。

那麼防線中一共有多少對華農兄弟呢?

Input

第一行一個 n

(1≤n≤2⋅1e5) 表示這道防線一共有多少個防禦點 第二行 n 個數表示第i個防禦點的防禦半徑 ai (1≤ai≤2⋅1e5)

 

Output

輸出華農兄弟的對數。

3

2 2 1

3

2 1 2

5

5 5 5 5 5

1

0

10

Hint

第一個樣例:1可以保護2,2也可以保護1,3只能保護自己,所以答案是1。

第三個樣例:任意兩個都是華農兄弟。

 

原題:2017CCPC 哈爾濱 A

在原題是 Manacher+樹狀數組

這道題我直接砍掉了Manacher但是難度也沒有減小多少,想到了就簡單,沒想到就難的很。

關鍵是想到怎麼處理兩個防禦點可以互相保護,暴力是過不了的,具體看代碼。

我以爲可以用樹狀數組和線段樹,沒想到yxz居然用主席樹過了,如果有奆佬用用其他辦法過的歡迎大家討論。

#include<bits/stdc++.h>
#define ll long long
#define qq printf("QAQ\n");
using namespace std;
const int maxn=2e5+5;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
ll quick_pow(ll a,int n)
{
    ll ans=1;
    while(n)
    {
        if(n&1)ans=ans*a%mod;
        n/=2;
        a=a*a%mod;
    }
    return ans;
}
int a[maxn],sum[maxn]={0};
vector<int>v[maxn];
int lowbit(int x)
{
    return x & - x;
}
void updata(int x,int data)
{
    while(x<maxn)
    {
        sum[x]+=data;
        x+=lowbit(x);
    }
}
int query(int x)
{
    int ans=0;
    while(x>0)
    {
        ans+=sum[x];
        x-=lowbit(x);
    }
    return ans;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]),v[max(1,i-a[i]+1)].push_back(i);
    ll ans= 0;
    for(int i=1;i<=n;i++)
    {
        for(int j=0;j<v[i].size();j++)
            updata(v[i][j],1);
        ans+=(ll)(query(min(maxn-1,i+a[i]-1))-query(i));
    }
    printf("%lld\n",ans);
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章