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。
第三個樣例:任意兩個都是華農兄弟。
在原題是 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;
}