jzoj 5821. 【NOIP提高A组模拟2018.8.16】 手机信号(set)

Description

这里写图片描述


Input

第一行由一个空格隔开的两个正整数 m, c,意义见题目描述。
接下来 m 行,每行可能有以下形式:
construct l r v 代表发生了第一种事件;
destruct l r 代表发生了第二种事件;
query x 代表发生了第三种事件。


Output

对于每个 query 操作,请输出一行一个整数代表此时坐标 x 处的信号强度。


Sample Input

11 10000
query 5
construct 5 500 100
query 500
query 1000
construct 10 90 5
query 44
destruct 44 66
query 55
construct 50 60 3
query 46
query 6000


Sample Output

0
975
0
9999
9775
9984
0


Data Constraint

这里写图片描述


Solution

这题我竟然调了一上午,各种奇怪的细节
对于construct,加入一个区间,如果一个区间包裹它,那么可以将区间分裂成两个(题目保证在新增区间内不会有信号站,所以可以直接分成两个),所以区间数最多2m个。
我们可以用set去维护(不会使用set的可以戳这里)。
用三元组 ( l , r , v ) (l,r,v) (l,r,v)表示一个区间。
每加入一个区间,就将一个三元组放入set。

  • Constuct:对于要加入的区间,判断是否存在区间包裹它,如果包裹,就把这个区间拆开。

  • Destruct:将直接包含的区间删除,在将有交集的删去,加入他不用被删的部分。如果需要删除的区间被一个区间包含在内,直接将这个区间分成两个即可。

  • Query:如果直接被一个区间包含,直接判断即可。否则就判断与旁边的两个区间那个更近。
    注意区间的端点。


Code

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#define iter set<node,cmp>::iterator 
#define LL long long 
using namespace std;
LL n,m;
struct node{
	LL l,r,v;
};
struct cmp{
	bool operator()(const node &a,const node &b) {
		return a.l<b.l;
	}
};
set<node,cmp> s;
LL find(node y ,LL x) {
	LL z=x-y.l,z1;
	z1=z/y.v+(z%y.v!=0);
	return y.l+z1*y.v;
}
int main() {
	freopen("cellphone.in","r",stdin);
	freopen("cellphone.out","w",stdout);
	LL i,j,k;
	scanf("%lld%lld",&n,&m);
	for (i=1;i<=n;i++) {
		scanf("\n");
		char c=getchar();
		if (c=='c') {
			scanf("onstruct");
			node x,y,z;scanf("%lld%lld%lld",&x.l,&x.r,&x.v);
			if (!s.empty()) {
				iter it=s.lower_bound(x);
				if (it!=s.begin()) {
					it--;y=*it;
					if (y.r>x.r) {
						LL zl=find(y,x.r);
						s.erase(it);
						if (zl<=y.r) z=y,z.l=zl,s.insert(z);
					}
					if (x.l-1>=y.l) {
						z=y;z.r=x.l-1;s.insert(z);
					}
				}
			}
			s.insert(x);
		}
		if (c=='d') {
			scanf("estruct");
			LL x,y;scanf("%lld%lld",&x,&y);
			node d;d.l=x,d.r=y;
			if (!s.empty()) {
				iter it=s.lower_bound(d);
				iter it1=it;
				node z1,z;
				if (it!=s.begin()) {
					it--;
					z=*it;
						if (z.r>=x) {
							s.erase(it);
							z1=z;z1.r=x-1;s.insert(z1);
							if (z.r>=y) {
								LL zl=find(z,y+1);
								if (zl<=z.r) z1=z,z1.l=zl,s.insert(z1);
							}
						} 
				}
				z=*it1;
				while (z.r<=y) {
					it=it1;
					if (it1==s.end()) break;
					it++;
					s.erase(it1);
					it1=it;
					z=*it1;
				}
				while (z.l<=y) {
					it=it1;
					if (it1==s.end()) break;
					it++;
					s.erase(it1);
					it1=it;
					LL zl=find(z,y+1);
					if (zl<=z.r) z1=z,z1.l=zl,s.insert(z1);
					z=*it1;
				}
			}
		}
		if (c=='q') {
			scanf("uery");
			LL x,ans=2100000000;scanf("%lld",&x);
			node d;d.l=x;
			if (!s.empty()){
				node z,z1;
				iter it=s.lower_bound(d);
				iter it1=it;
				if (it!=s.begin()) {
					it--;z=*it;
					if (z.r>=x) {
						LL zl=find(z,x),zl1;
						zl1=zl-z.v;
						if (z.r>=zl) ans=min(abs(zl-x),ans);
						if (z.l<=zl1) ans=min(abs(zl1-x),ans);
					}
					{
						z1=*it1;
						if (it1!=s.end()) ans=min(abs(z1.l-x),ans);
						LL y=z.l+((z.r-z.l)/z.v)*z.v;
						ans=min(ans,abs(x-y));
					}
				}
				else {
					z1=*it1;
					ans=abs(z1.l-x);
				}
				printf("%lld",max(m-ans*ans,(LL)0));
			}
			else printf("0");
			printf("\n");
		}
		
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值