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;
}
发布了37 篇原创文章 · 获赞 14 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/swust5120166213/article/details/86703350
今日推荐