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");
}
}
}