题解
- c++有c++的优势,这题可以用c++里STL库里的set来做(平衡树)
- 每次可以将形如(l,r,v)的一个三元组插入set
- 但是,可以发现对于下面的操作的话,l和r都有信号站会更好处理,所以把r定到最后一个信号站的位置
- 对于插入操作,我们发现,当前插入的区间,可以会被之前插入的区间所包含,那么就会把一个区间分成两个部分
- 因为题目保证插入操作[l,r]中没有型号站,那么如果被包含的话
- 就一定可以把大区间分成两个区间,至于分出来的区间的左右坐标也要满足l和r都有信号站
- 那么就会分成[B.l,S.l-1-(S.l-1-B.l)%B.v]和[S.r+1+(B.r-S.r-1)%B.v,B.r]
- 对于删除操作,也就是把与[l,r]区间相交的区间都要分出不在[l,r]区间的部分
- 那么就一共有四种情况:
- ①一个区间的左边和[l,r]相交
- ②一个区间的右边和[l,r]相交
- ③一个区间包含[l,r]
- ④[l,r]包含一个区间
- 注意,还是要满足区间的左右区间都是信号站
- 对于查询操作,就是找到x向左右区间延伸的第一个l和r,和跨过x的区间
- 这题主要就是一道考验细节的题目了
代码
1 #include <cstdio>
2 #include <iostream>
3 #include <set>
4 using namespace std;
5 struct edge { int l,r,v; }a,b,t;
6 struct cmp { bool operator()(const edge &a,const edge &b) { return a.l<b.l; } };
7 int m,ans,inf=1000000010;
8 long long c,tot;
9 char str[10];
10 set<edge,cmp>Q;
11 int main()
12 {
13 freopen("cellphone.in","r",stdin);
14 freopen("cellphone.out","w",stdout);
15 scanf("%d%lld",&m,&c);
16 for(int i=1;i<=m;i++)
17 {
18 scanf("%s",str);
19 if (str[0]=='c')
20 {
21 scanf("%d%d%d",&a.l,&a.r,&a.v);
22 a.r=a.r-(a.r-a.l)%a.v; b=a;
23 set<edge,cmp>::iterator k=Q.lower_bound(b);
24 if (k!=Q.begin())
25 {
26 k--;b=*k;
27 if (b.r>=a.l)
28 {
29 Q.erase(k);
30 t=b; t.r=a.l-1-(a.l-1-t.l)%t.v; Q.insert(t);
31 t=b; t.l=a.r+1+(t.r-a.r-1)%t.v; Q.insert(t);
32 }
33 }
34 Q.insert(a);
35 }
36 if (str[0]=='d')
37 {
38 scanf("%d%d",&a.l,&a.r);
39 set<edge,cmp>::iterator k=Q.lower_bound(a);
40 set<edge,cmp>::iterator p;
41 if (k!=Q.begin())
42 {
43 k--;p=k++;b=*p;
44 if (b.r>=a.l)
45 {
46 Q.erase(p);
47 t=b; t.r=a.l-1-(a.l-1-t.l)%t.v; Q.insert(t);
48 if (b.r>a.r)
49 {
50 t=b; t.l=a.r+1+(t.r-a.r-1)%t.v; Q.insert(t);
51 continue;
52 }
53 }
54 }
55 b=*k;
56 for (;k!=Q.end()&&b.l<=a.r;)
57 {
58 p=k++; Q.erase(p);
59 if (b.r>a.r)
60 {
61 b.l=a.r+1+(b.r-a.r-1)%b.v; Q.insert(b);
62 break;
63 }
64 b=*k;
65 }
66 }
67 if (str[0]=='q')
68 {
69 scanf("%d",&a.l);
70 if (Q.empty()) { printf("0\n"); continue; }
71 set<edge,cmp>::iterator k=Q.lower_bound(a);
72 ans=inf;
73 if (k!=Q.end()) b=*k,ans=b.l-a.l;
74 if (k!=Q.begin()) k--;
75 b=*k;
76 if (b.l<=a.l)
77 {
78 if (b.r<=a.l) ans=min(ans,a.l-b.r);
79 else ans=min(ans,min((a.l-b.l)%b.v,(b.r-a.l)%b.v));
80 }
81 printf("%lld\n",(c-1ll*ans*1ll*ans)>0?(c-1ll*ans*1ll*ans):0);
82 }
83 }
84 return 0;
85 }