BZOJ 5017: [Snoi2017] + bomb strongly connected components segment tree built FIG Optimization

title

BZOJ 5017
LUOGU 5025
Description

There are in a straight line \ (N \) bomb, the bomb is coordinates of each \ (X_i \) , blast radius \ (R_i \) , when a bomb, the bomb if another location \ (x_j \ ) satisfies: \ (X_i-R_i≤Xj≤X_i + R_i \) , then the bomb will be detonated. Now, would you please help calculate, first of \ (i \) bomb detonated, how many bombs will detonate it?
The answer to \ (1000000007 \) modulo

Input

The first line, a digital \ (N \) , indicates the number of bombs. Second \ (2 ~ N + 1 \ ) rows, each row \ (2 \) digits representing \ (X_i \) , \ (R_i \) , to ensure \ (X_i \) is strictly increasing.

Output
A number that \ (\ sum \ limits_ {i = 1} ^ ni \ times i × \) bomb (I \) \ number can be detonated bomb.

Sample Input

4
1 1
5 1
6 5
15 15

Sample Output

32

analysis

Began to fill \ (blog \) , a little uncomfortable, after all, recalled the idea some difficulties.

  • Title short, there is also a good nature, a napalm bomb to the range is a range , but tell the truth, I was in the initial problem-solving process and not pay attention to this very nature, the discovery also directly skipped.
    • We consider violence algorithm, for each bomb, they can blow up the bomb to even the edges, for each other to be able to blow up a bomb, which can be deep-fried to a certain interval is the same, so use \ (tarjan \) be a directed graph condensing point, this for the remaining \ (the DAG \) be \ (DP \) , counts the number of descendants of a point, \ (F [I] [J] \) represents \ (J \) points whether \ (I \) offspring , are time and space complexity \ (O (^ n-2) \) , not very excellent.
    • Consider the set of descendants of a point of a certain segment is a contiguous, so \ (DP \) Maximum referred child node when the lowest number to the space complexity turn into \ (O (n-) \) . Because the key to this algorithm is too much even side, so we will use the so-called beautiful nature found above carry out his things out, consider the tree line optimization map building, the number of points still \ (O (the n-) \) , edge number of optimizations to \ (O (nlogn) \) .
    • This is to our seniors taught problem-solving methods to optimize the construction segment tree diagram, for the questions, it can not be said to be the best solution, but the method of optimizing the construction segment tree diagram will indeed have to be, \ (NOI2019 ~ D2 ~ T1 \) is \ (72pts \) violence is the use of this algorithm, a pity that I did not learn (and it has not learned, QwQ).
  • What lazy, so to learn this \ (O (n) \) algorithm.
    • Even without considering the side when the segment tree diagram optimization built, but consider for each point to find the left and right sides, respectively, of napalm nearest to their point, the two points connected to their own side . It is easy to find, for each point connected only to the two sides, the complexity of the \ (O (n-) \) .
    • The total complexity, because you want to count discrete complexity, it is \ (O (nlogn) \) , but this question seems to discrete somewhat tasteless, but I do not want to write a radix sort.
    • Reference: zhouyuheng2003 .
  • To sum up then, like useful tips, such as optimizing the construction segment tree diagram, which must have the will; But for the subject itself, going to hold him optimal solution, of course, you just take this problem to practice hand, I it does not matter.

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn=5e5+10,mod=1e9+7;

char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
    x=0;
    T f=1, ch=getchar();
    while (!isdigit(ch) && ch^'-') ch=getchar();
    if (ch=='-') f=-1, ch=getchar();
    while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
    x*=f;
}

template<typename T>inline void write(T x)
{
    if (!x) { putchar('0'); return ; }
    if (x<0) putchar('-'), x=-x;
    T num=0, ch[20];
    while (x) ch[++num]=x%10+48, x/=10;
    while (num) putchar(ch[num--]);
}

struct Orz{ll x,l,r;}a[maxn];
int ver[maxn<<1],Next[maxn<<1],head[maxn],len;
inline void add(int x,int y)
{
    ver[++len]=y,Next[len]=head[x],head[x]=len;
}

int dfn[maxn],low[maxn],id,n;
int Stack[maxn],top;
int belong[maxn],tot;
int ls[maxn],rs[maxn];
bool instack[maxn];
inline void tarjan(int x)
{
    dfn[x]=low[x]=++id;
    Stack[++top]=x;
    instack[x]=1;
    for (int i=head[x]; i; i=Next[i])
    {
        int y=ver[i];
        if (!dfn[y])
        {
            tarjan(y);
            low[x]=min(low[x],low[y]);
        }
        else if (instack[y])
            low[x]=min(low[x],dfn[y]);
    }
    if (low[x]==dfn[x])
    {
        int k;
        ls[++tot]=n+1;
        do
        {
            k=Stack[top--];
            ls[tot]=min(ls[tot],(int)a[k].l);
            rs[tot]=max(rs[tot],(int)a[k].r);
            belong[k]=tot;
            instack[k]=0;
        } while (k!=x);
    }
}

int vc[maxn<<1],Nc[maxn<<1],hc[maxn],deg[maxn],lc;
inline void addc(int x,int y)
{
    if (x==y) return ;
    vc[++lc]=y,Nc[lc]=hc[x],hc[x]=lc,++deg[y];
}

ll b[maxn];
int main()
{
    read(n);
    for (int i=1; i<=n; ++i) read(a[i].x),read(a[i].r),b[i]=a[i].x;
    for (int i=1; i<=n; ++i)
    {
        a[i].l=lower_bound(b+1,b+n+1,a[i].x-a[i].r)-b;
        a[i].r=upper_bound(b+1,b+n+1,a[i].x+a[i].r)-b-1;
        a[i].x=lower_bound(b+1,b+n+1,a[i].x)-b;
    }
    for (int i=1; i<=n; ++i)
    {
        while (top && a[Stack[top]].r<a[i].x) --top;
        if (top && a[Stack[top]].r>=a[i].x) add(Stack[top],i);
        while (top && a[Stack[top]].r<=a[i].r) --top;
        Stack[++top]=i;
    }
    top=0;
    for (int i=n; i>=1; --i)
    {
        while (top && a[Stack[top]].l>a[i].x) --top;
        if (top && a[Stack[top]].l<=a[i].x) add(Stack[top],i);
        while (top && a[Stack[top]].l>=a[i].l) --top;
        Stack[++top]=i;
    }

    for (int i=1; i<=n; ++i)
        if (!dfn[i]) tarjan(i);
    for (int k=1; k<=n; ++k)
        for (int i=head[k]; i; i=Next[i])
        {
            int y=ver[i];
            addc(belong[y],belong[k]);
        }

    queue<int>q;
    for (int i=1; i<=n; ++i)
        if (!deg[i]) q.push(i);
    while (!q.empty())
    {
        int x=q.front();
        q.pop();
        for (int i=hc[x]; i; i=Nc[i])
        {
            int y=vc[i];
            ls[y]=min(ls[y],ls[x]);
            rs[y]=max(rs[y],rs[x]);
            if (!--deg[y]) q.push(y);
        }
    }
    ll res=0;
    for (int i=1; i<=n; ++i) res=(res+1ll*i*(rs[belong[i]]-ls[belong[i]]+1))%mod;
    write(res),puts("");
    return 0;
}

Guess you like

Origin www.cnblogs.com/G-hsm/p/11323333.html