炸弹 线段树优化建边

10 篇文章 0 订阅
3 篇文章 0 订阅

 

线段树优化建边好题

但是数据太水了

发现每个炸弹干涉的区间是连续的考虑优化建边

然后明显Tarjan缩点

这里需要发现一个性质

因为对于一张top图寻找从一个点开始到别的点所有siz没有On做法

唯一的比较优的做法是bitset优化的传递闭包

但是这道题不一样

观察发现联通块是连续的所以记录一下向左最远和向右最远

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#include<stack>
typedef int INT;
const int INF=1e9+7;
const int mod=1e9+7;
#define int long long
#define lc (p<<1)
#define rc (p<<1|1)
const int N=8e5+100;

namespace fastIO{
    #define BUF_SIZE 100000
    #define OUT_SIZE 100000
    #define ll long long
    //fread->read
    bool IOerror=0;
    inline char nc(){
        static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
        if (p1==pend){
            p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);
            if (pend==p1){IOerror=1;return -1;}
            //{printf("IO error!\n");system("pause");for (;;);exit(0);}
        }
        return *p1++;
    }
    inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
    inline void read(ll &x){
        bool sign=0; char ch=nc(); x=0;
        for (;blank(ch);ch=nc());
        if (IOerror)return;
        if (ch=='-')sign=1,ch=nc();
        for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
        if (sign)x=-x;
    }
    inline void read(double &x){
        bool sign=0; char ch=nc(); x=0;
        for (;blank(ch);ch=nc());
        if (IOerror)return;
        if (ch=='-')sign=1,ch=nc();
        for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
        if (ch=='.'){
            double tmp=1; ch=nc();
            for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');
        }
        if (sign)x=-x;
    }
    inline void read(char *s){
        char ch=nc();
        for (;blank(ch);ch=nc());
        if (IOerror)return;
        for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
        *s=0;
    }
    inline void read(char &c){
        for (c=nc();blank(c);c=nc());
        if (IOerror){c=-1;return;}
    }
    //getchar->read
    inline void read1(int &x){
        char ch;int bo=0;x=0;
        for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
        for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
        if (bo)x=-x;
    }
    inline void read1(double &x){
        char ch;int bo=0;x=0;
        for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
        for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
        if (ch=='.'){
            double tmp=1;
            for (ch=getchar();ch>='0'&&ch<='9';tmp/=10.0,x+=tmp*(ch-'0'),ch=getchar());
        }
        if (bo)x=-x;
    }
    inline void read1(char *s){
        char ch=getchar();
        for (;blank(ch);ch=getchar());
        for (;!blank(ch);ch=getchar())*s++=ch;
        *s=0;
    }
    inline void read1(char &c){for (c=getchar();blank(c);c=getchar());}
    //scanf->read
    inline void read2(int &x){scanf("%d",&x);}
    inline void read2(double &x){scanf("%lf",&x);}
    inline void read2(char *s){scanf("%s",s);}
    inline void read2(char &c){scanf(" %c",&c);}
    inline void readln2(char *s){gets(s);}
    //fwrite->write
    struct Ostream_fwrite{
        char *buf,*p1,*pend;
        Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;}
        void out(char ch){
            if (p1==pend){
                fwrite(buf,1,BUF_SIZE,stdout);p1=buf;
            }
            *p1++=ch;
        }
        void print(int x){
            static char s[15],*s1;s1=s;
            if (!x)*s1++='0';if (x<0)out('-'),x=-x;
            while(x)*s1++=x%10+'0',x/=10;
            while(s1--!=s)out(*s1);
        }
        void println(int x){
            static char s[15],*s1;s1=s;
            if (!x)*s1++='0';if (x<0)out('-'),x=-x;
            while(x)*s1++=x%10+'0',x/=10;
            while(s1--!=s)out(*s1); out('\n');
        }
        void print(double x,int y){
            static ll mul[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,
                1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
                100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL};
            if (x<-1e-12)out('-'),x=-x;x*=mul[y];
            ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1;
            ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2);
            if (y>0){out('.'); for (size_t i=1;i<y&&x3*mul[i]<mul[y];out('0'),++i); print(x3);}
        }
        void println(double x,int y){print(x,y);out('\n');}
        void print(char *s){while (*s)out(*s++);}
        void println(char *s){while (*s)out(*s++);out('\n');}
        void flush(){if (p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}}
        ~Ostream_fwrite(){flush();}
    }Ostream;
    inline void print(int x){Ostream.print(x);}
    inline void println(int x){Ostream.println(x);}
    inline void print(char x){Ostream.out(x);}
    inline void println(char x){Ostream.out(x);Ostream.out('\n');}
    inline void print(double x,int y){Ostream.print(x,y);}
    inline void println(double x,int y){Ostream.println(x,y);}
    inline void print(char *s){Ostream.print(s);}
    inline void println(char *s){Ostream.println(s);}
    inline void println(){Ostream.out('\n');}
    inline void flush(){Ostream.flush();}
    //puts->write
    char Out[OUT_SIZE],*o=Out;
    inline void print1(int x){
        static char buf[15];
        char *p1=buf;if (!x)*p1++='0';if (x<0)*o++='-',x=-x;
        while(x)*p1++=x%10+'0',x/=10;
        while(p1--!=buf)*o++=*p1;
    }
    inline void println1(int x){print1(x);*o++='\n';}
    inline void print1(char c){*o++=c;}
    inline void println1(char c){*o++=c;*o++='\n';}
    inline void print1(char *s){while (*s)*o++=*s++;}
    inline void println1(char *s){print1(s);*o++='\n';}
    inline void println1(){*o++='\n';}
    inline void flush1(){if (o!=Out){if (*(o-1)=='\n')*--o=0;puts(Out);}}
    struct puts_write{
        ~puts_write(){flush1();}
    }_puts;
    inline void print2(int x){printf("%d",x);}
    inline void println2(int x){printf("%d\n",x);}
    inline void print2(char x){printf("%c",x);}
    inline void println2(char x){printf("%c\n",x);}
    inline void println2(){printf("\n");}
    #undef ll
    #undef OUT_SIZE
    #undef BUF_SIZE
};
using namespace fastIO;
struct Node{
	int x,r;
}A[N];
struct Front_star{
	int u,v,nxt;
}e[N<<3];
int cnt=0;
int first[N<<2];
void add(int u,int v){
	++cnt;
	e[cnt].u=u;
	e[cnt].v=v;
	e[cnt].nxt=first[u];
	first[u]=cnt;
}
int rd[N<<2];
int ecnt=0;
int head[N<<2];
void Insert(int u,int v){
	++ecnt;
	++rd[v];
	e[ecnt].u=u;
	e[ecnt].v=v;
	e[ecnt].nxt=head[u];
	head[u]=ecnt;
}
int lson[N<<2];
int rson[N<<2];
int Id[N];
int tot=0;
int n;
void Build(int p,int l,int r){
	lson[p]=l;
	rson[p]=r;
	tot=max(tot,p);
	if(l==r){
		Id[l]=p;
		return;
	}
	int mid=(l+r)>>1;
	add(p,lc);
	add(p,rc);
	Build(lc,l,mid);
	Build(rc,mid+1,r);
}
void Update(int p,int l,int r,int rt){
	if(l<=lson[p]&&rson[p]<=r){
		add(rt,p);
		return;
	}
	int mid=(lson[p]+rson[p])>>1;
	if(l<=mid)Update(lc,l,r,rt);
	if(mid< r)Update(rc,l,r,rt);
}
//
//
int pos[N];
stack<int> S;
int Q[N<<2];
int he=0;
int ta=0;
int low[N<<2];
int dfn[N<<2];
int vis[N<<2];
int Belong[N<<2];
int scc=0;
int tcnt=0;
int L[N<<2],R[N<<2];
void Tarjan(int u){
	low[u]=dfn[u]=++tcnt;
	S.push(u);
	vis[u]=1;
	for(int i=first[u];i;i=e[i].nxt){
		int v=e[i].v;
		if(!dfn[v]){
			Tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else{
			if(vis[v])low[u]=min(low[u],dfn[v]);
		}
	}
	if(dfn[u]==low[u]){
		int x;
		scc++;
		L[scc]=INF;
		do{
			x=S.top();
			S.pop();
			vis[x]=0;
			L[scc]=min(L[scc],lson[x]);
			R[scc]=max(R[scc],rson[x]);
			Belong[x]=scc;
		}while(x!=u);
	}
}
void Rebuild(){
	for(int u=1;u<=tot;++u){
		for(int i=first[u];i;i=e[i].nxt){
			int v=e[i].v;
			if(Belong[u]!=Belong[v]){
				Insert(Belong[u],Belong[v]);
			}
		}		
	}

}
void TopSort(){
	for(int i=1;i<=scc;++i){
		if(!rd[i])Q[++ta]=i;
	}
	while(he<ta){
		int x=Q[++he];
		for(int i=head[x];i;i=e[i].nxt){
			int v=e[i].v;
			rd[v]--;
			if(!rd[v])Q[++ta]=v;
		}
	}
	for(int i=scc;i>=1;--i){
		int x=Q[i];
		for(int i=head[x];i;i=e[i].nxt){
			int v=e[i].v;
			L[x]=min(L[v],L[x]);
			R[x]=max(R[v],R[x]);
		}
	}
}
INT main(){
//	freopen("test.in","r",stdin);
//	freopen("test.out","w",stdout);
int size=40<<20;//40M
	__asm__ ("movq %0,%%rsp\n"::"r"((char*)malloc(size)+size));
	read(n);
	for(int i=1;i<=n;++i){
		read(A[i].x);
		read(A[i].r);
		pos[i]=A[i].x;
	}
	Build(1,1,n);
	for(int i=1;i<=n;++i){
		int lpos=lower_bound(pos+1,pos+1+n,A[i].x-A[i].r)-pos;
		int rpos=upper_bound(pos+1,pos+1+n,A[i].x+A[i].r)-pos-1;
		if(lpos==rpos)continue;
		Update(1,lpos,rpos,Id[i]);
	}
	for(int i=1;i<=tot;++i){
		if(!dfn[i])Tarjan(i);
	}
	Rebuild();
	TopSort();
	int ans=0;
	for(int i=1;i<=n;++i){
		ans=(ans+i*(R[Belong[Id[i]]]-L[Belong[Id[i]]]+1)%mod)%mod;
	}
	cout<<ans;
	exit(0);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值