求助,自己想的一个思路,LOJ上满分,洛谷72
查看原帖
求助,自己想的一个思路,LOJ上满分,洛谷72
220838
yql123456SN弱校小菜鸡楼主2020/6/12 20:58

自己想的一个思路,把每个炸弹引爆的其他炸弹拆成左右两个区间分别dp(不是那个On错解),因为可能出现左右跳的情况,所以要记忆化搜索。

#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std; //预定义/预处理  
#define inf 2000000000000000005
#define rg register 
#define int long long 
#define ull unsigned long long
inline int read() 
{ 
    rg int x = 0; 
    	rg int flag = 1; 
    rg char ch = getchar(); 
    while(ch < '0' or ch > '9') 
    {
        if(ch == '-') 
            flag = -1; 
            ch = getchar();
    } 
    while(ch >= '0' and ch <= '9') 
    {
        x = x * 10 + ch - '0'; 
        ch = getchar();
    } 
    return x * flag; 
} 
inline void write(int x,char end='\n')
{
	if(x==0)
    {
    	putchar('0');
        putchar(end);
        return;
    }
   char F[205];
    rg int tmp=x>0?x:-x ;
    if(x<0)putchar('-') ;
	    int cnt=0 ;
    while(tmp>0)
    {
	    F[cnt++]=tmp%10+'0';
    	tmp/=10;        
	}

	    while(cnt>0) putchar(F[--cnt]);
	    putchar(end);
	    return;
 }
inline int ksm(int di,int mi,int mod)
{
    int an=1;
    while(mi)
    {
        if(mi&1)
            an=an*di%mod;
        mi>>=1;
        di=di*di%mod;
    }
    return an;
}
inline int mul(int di,int mi,int mod)
{
    int an=0;
    int f=(mi<0?-1:1);
    f*=(di<0?-1:1);
    mi=abs(mi);
    di=abs(di);
    while(mi)
    {
        if(mi&1)
            an=(an+di)%mod;
        mi>>=1;
        di=(di+di)%mod;
    }
    return an*f;
}
#define ma 500005
map<int,int> vis;
int book[ma<<4];
int cnt;
int find(int i)
{
	int l=1,r=cnt;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(book[mid]==i) return mid;
		if(book[mid]>i) r=mid-1;
		else l=mid+1;
	}
	return -1;
}
bool lisan(int x,int y)
{
	return x<y;
}
inline void ins(int x)
{
	if(!vis[x]) vis[x]=1,book[++cnt]=x;
}



struct bong
{
	int l,r,x,id;
	bong(){}
	bong(int ll,int rr,int xx,int iid)
	{
		l=ll;
		r=rr;
		x=xx;
		id=iid;
	}
}in[ma];
inline bool cmp(bong x,bong y)
{
	return x.x<y.x;
}
const int deta=1e18+1;
const int mo=1e9+7;
const int de=(ma<<4)+(ma<<2);
//线段树
int root;
int ls[de],rs[de],ll[de],rr[de],tot,idl[de],idr[de],s[de];
inline void New(int &i)
{
	i=++tot;
	ll[i]=inf;
	rr[i]=-inf;
	return;
}
inline void push_up(int i)
{
	ll[i]=min(ll[ls[i]],ll[rs[i]]);
	rr[i]=max(rr[ls[i]],rr[rs[i]]);
	idl[i]=(ll[i]==ll[ls[i]]? idl[ls[i]]:idl[rs[i]]);
	idr[i]=(rr[i]==rr[ls[i]]? idr[ls[i]]:idr[rs[i]]);
	if(ll[ls[i]]==ll[rs[i]]) idl[i]=min(idl[ls[i]],idl[rs[i]]);
	if(rr[ls[i]]==rr[rs[i]]) idr[i]=max(idr[ls[i]],idr[rs[i]]);
	s[i]=(s[ls[i]]+s[rs[i]]);
	return;
}
void add(int &i,int l,int r,int pos,bong v)
{
	if(l>r) return;
	if(!i) New(i);
	if(l==r)
	{
		idl[i]=idr[i]=v.id;
		ll[i]=v.l;
		rr[i]=v.r;
		s[i]=1;
		return;
	}
	int mid=(l+r)>>1;
	if(pos<=mid) add(ls[i],l,mid,pos,v);
	else add(rs[i],mid+1,r,pos,v);
	push_up(i);
	return;
}
int suml(int i,int l,int r,int L,int R)
{
	if(L>R) return 0;
	if(!i) return 0;
	if(L<=l&&r<=R) return idl[i];
	int ans=0,mid=(l+r)>>1;
	if(L<=mid) ans=suml(ls[i],l,mid,L,R);
	if(mid+1<=R) 
	{
		int an=suml(rs[i],mid+1,r,L,R);
		if(in[an].l<in[ans].l||(in[an].l==in[ans].l&&an<ans)) ans=an;
	}
	return ans;
}
int sumr(int i,int l,int r,int L,int R)
{
	if(L>R) return 0;
	if(!i) return 0;
	if(L<=l&&r<=R) return idr[i];
	int ans=0,mid=(l+r)>>1;
	if(L<=mid) ans=sumr(ls[i],l,mid,L,R);
	if(mid+1<=R) 
	{
		int an=sumr(rs[i],mid+1,r,L,R);
		if(in[an].r>=in[ans].r||(in[an].r==in[ans].r&&an>ans)) ans=an;
	}
	return ans;
}
int sum(int i,int l,int r,int L,int R)
{
	if(L>R) return 0;
	if(!i) return 0;
	if(L<=l&&r<=R) return s[i];
	int ans=0,mid=(l+r)>>1;
	if(L<=mid) ans+=sum(ls[i],l,mid,L,R);
	if(mid+1<=R) ans+=sum(rs[i],mid+1,r,L,R);
	return ans;
}
int dpl[ma],dpr[ma];
int DPL(int now)
{
	if(dpl[now]!=-1) return dpl[now];
	int better=suml(root,1,cnt,in[now].l,in[now].r);
	if(better>now)
	{
		dpl[better]=DPL(better);
		return dpl[now]=dpl[better]-(better-now);
	}
	if(better==now)
		return dpl[now]=sum(root,1,cnt,in[now].l,in[now].x-1);
	if(dpl[better]==-1) 
	{
		cout<<"AHHHHHH\n";
		exit(0);
	}
	return dpl[now]=dpl[better]+(now-better);
}
int DPR(int now)
{
	if(dpr[now]!=-1) return dpr[now];
	int better=sumr(root,1,cnt,in[now].l,in[now].r);
	if(better<now)
	{
		dpr[better]=DPR(better);
		return dpr[now]=dpr[better]-(now-better);
	}
	if(better==now)
		return dpr[now]=sum(root,1,cnt,in[now].x+1,in[now].r);
	if(dpr[better]==-1) 
	{
		cout<<"AHHHHHH\n";
		exit(0);
	}
	return dpr[now]=dpr[better]+(better-now);
}
signed main()
{
	memset(dpl,-1,sizeof(dpl));
	memset(dpr,-1,sizeof(dpr));
	int n=read();
	in[0]=bong(inf,-inf,0,0);
	ll[0]=inf;
	rr[0]=-inf;
	int r,ans=0;
	for(int i=1;i<=n;i++) 
	{
		in[i].x=read();
		r=read();
		in[i].l=in[i].x-r;
		in[i].r=in[i].x+r;
		ins(in[i].x);
		ins(in[i].l);
		ins(in[i].r);
	}
	sort(book+1,book+cnt+1,lisan);
	sort(in+1,in+n+1,cmp);
	for(int i=1;i<=n;i++)
	{
		in[i].x=find(in[i].x);
		in[i].l=find(in[i].l);
		in[i].r=find(in[i].r);
		in[i].id=i;
		add(root,1,cnt,in[i].x,in[i]);
	}
	for(int i=1;i<=n;i++)
		if(dpl[i]==-1) dpl[i]=DPL(i);
	for(int i=n;i>=1;i--)
		if(dpr[i]==-1) dpr[i]=DPR(i);
	for(int i=1;i<=n;i++) ans=(ans+(dpl[i]+dpr[i]+1)%mo*i%mo)%mo;
	write(ans);
}
/*
4
1 1
5 1
6 5
15 15
*/

求错。。。hack数据也行(尽量小一点) 谢谢大佬们,感激不尽

2020/6/12 20:58
加载中...