题意

test20180921 手机信号_ios
test20180921 手机信号_#include_02

分析

我们用形如(l, r, v) 的三元组描述一个区间,这个区间中从l 到r 每隔v 有一个信号站。
考虑一次construct 操作,会添加一个新的区间,并可能将一个已经存在的区间分裂为两个。
因此任何时刻区间总数不会超过\(O(n)\) 个。
我们用一个数据结构维护所有区间(比如说set),在询问时二分查找即可。
时间复杂度\(O(n \log n)\)

学习了。
我昨天打了一个set套区间端点,炸了,觉得分类太多没法打。
主要是因为不知道怎么查找区间的左右位置。
原来是分别查找左端点lower_bound-1和右端点upper_bound-1

代码
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<ctime>
#include<iostream>
#include<string>
#include<vector>
#include<list>
#include<deque>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<complex>
#pragma GCC optimize ("O0")
using namespace std;
template<class T> inline T read(T&x)
{
    T data=0;
	int w=1;
    char ch=getchar();
    while(!isdigit(ch))
    {
		if(ch=='-')
			w=-1;
		ch=getchar();
	}
    while(isdigit(ch))
        data=10*data+ch-'0',ch=getchar();
    return x=data*w;
}
typedef long long ll;
const int INF=0x7fffffff;

int m;
ll c;

struct node
{
	int l,r,v;
	bool operator<(const node&rhs)const
	{
		return l<rhs.l;
	}
};

set<node>S;
typedef set<node>::iterator sit;

int getlp(int l,int v,int p)
{
	return l+(p-l)/v*v;
}

int getrp(int r,int v,int p)
{
	return r-(r-p)/v*v;
}

void construct(int l,int r,int v)
{
	r=getlp(l,v,r);
	sit i=S.lower_bound((node){l,0,0});
	if(i!=S.begin())
	{
		--i;
		if(i->l<l&&i->r>r)
		{
			node t=*i;
			S.erase(i);
			int tt=getlp(t.l,t.v,l);
			S.insert((node){t.l,tt,t.v});
			tt=getrp(t.r,t.v,r);
			S.insert((node){tt,t.r,t.v});
		}
	}
	S.insert((node){l,r,v});
}

void destruct(int l,int r)
{
	sit i=S.lower_bound((node){l,0,0});
	if(i!=S.begin())
	{
		--i;
		if(i->l<l&&i->r>=l)
		{
			node t=*i;
			S.erase(i);
			int tt=getlp(t.l,t.v,l-1);
			S.insert((node){t.l,tt,t.v});
		}
	}
	i=S.upper_bound((node){r,0,0});
	if(i!=S.begin())
	{
		--i;
		if(i->l<=r&&i->r>r)
		{
			node t=*i;
			S.erase(i);
			int tt=getrp(t.r,t.v,r+1);
			S.insert((node){tt,t.r,t.v});
		}
	}
	S.erase(S.lower_bound((node){l,0,0}),S.upper_bound((node){r,0,0}));
}

ll query(int x)
{
	sit i=S.lower_bound((node){x,0,0});
	int ans=INF;
	if(i!=S.end())
		ans=min(ans,i->l-x);
	if(i!=S.begin())
	{
		--i;
		if(i->r>=x)
		{
			int t1=getlp(i->l,i->v,x),t2=getrp(i->r,i->v,x);
			ans=min(ans,min(x-t1,t2-x));
		}
		else
			ans=min(ans,x-i->r);
	}
	if(ans==INF)
		return 0;
	else
		return max(0ll,c-(ll)ans*ans);
}

int main()
{
  freopen("cellphone.in","r",stdin);
  freopen("cellphone.out","w",stdout);
	read(m);read(c);
	char opt[20];
	int x,y,z;
	while(m--)
	{
		scanf("%s",opt);
		if(opt[0]=='c')
		{
			read(x);read(y);read(z);
			construct(x,y,z);
		}
		else if(opt[0]=='d')
		{
			read(x);read(y);
			destruct(x,y);
		}
		else if(opt[0]=='q')
		{
			read(x);
			printf("%lld\n",query(x));
		}
	}
//  fclose(stdin);
//  fclose(stdout);
    return 0;
}