[set] Jzoj P5821 手机信号

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

题解

  • 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 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/9494974.html