首页 > 其他 > 详细

ACDream - Crayon

时间:2014-07-22 23:37:37      阅读:394      评论:0      收藏:0      [点我收藏+]

题目:

Description

There are only one case in each input file, the first line is a integer N (N ≤ 1,000,00) denoted the total operations executed by Mary.

Then following N lines, each line is one of the folling operations.

  • D L R : draw a segment [L, R], 1 ≤ L ≤  R ≤ 1,000,000,000.
  • C I : clear the ith added segment. It’s guaranteed that the every added segment will be cleared only once.
  • Q L R : query the number of segment sharing at least a common point with interval [L, R]. 1 ≤ L ≤ R ≤ 1,000,000,000.

Input

n

Then following n operations ...

Output

For each query, print the result on a single line ...

Sample Input

6
D 1 3
D 2 4
Q 2 3
D 2 4
C 2
Q 2 3

Sample Output

2
2

  题意:给出三种操作:①画一条占据[L,R]区间的线段,②去掉前面画的第i条线段(保证合法),③查询一条占据区间[L,R]的线段与前面多少条线段至少有一个公共点。对于③操作,输出结果。
区间范围[1,1000000000],操作最多100000次。
  区间很大,但是操作相对比较少,所以可以先对坐标离散化,然后缩小了范围以后再对数据操作。
  怎样去统计有多少条线段覆盖了某一段?这里用的方法是统计线段的两个端点,用树状数组来记录。这里需要开两个树状数组,一个用来记录左端点,一个用来记录右端点,然后每一次求某一段[L,R]有多少条线段经过的话,我们可以先求出有多少条线段的左端点在R的左边,这里只要求前段和就可以了,然后我们再求一下有多少线段的右端点在L的左边,同样求一次和,然后相减就可以得到结果了。
  为什么可以这样做?首先是因为线段有两个端点,然后两次求和都直接排除了R右边的无关线段,而在L左边的线段的两个端点都在L的左边,所以就会先算了一次,然后再被减回去。

代码:
bubuko.com,布布扣
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <vector>
 6 #define lowbit(x) (x & (-x))
 7 #define MAX 100201
 8 #define LL long long
 9 using namespace std;
10 
11 typedef struct{
12     LL l,r,k;
13     char ch;
14 }Seg;
15 Seg s[MAX];
16 LL l[MAX<<1],r[MAX<<1];
17 vector<LL> d;
18 LL tot,no,N[MAX];
19 
20 void add(LL p[],LL x,LL e){
21     for(;x<=tot;x+=lowbit(x)) p[x]+=e;
22 }
23 
24 LL query(LL p[],LL x){
25     LL ans=0;
26     for(;x>0;x-=lowbit(x)) ans+=p[x];
27     return ans;
28 }
29 
30 int main()
31 {
32     LL n,loc,ans;
33     //freopen("data.txt","r",stdin);
34     ios::sync_with_stdio(false);
35     while(cin>>n){
36         d.clear();
37         d.push_back(-(1<<30));
38         memset(l,0,sizeof(l));
39         memset(r,0,sizeof(r));
40         no=0;
41         for(LL i=0;i<n;i++){
42             cin>>s[i].ch;
43             if(s[i].ch==C){
44                 cin>>s[i].k;
45             }else{
46                 cin>>s[i].l>>s[i].r;
47                 if(s[i].ch==D)    N[++no]=i;
48                 d.push_back(s[i].l);
49                 d.push_back(s[i].r);
50             }
51         }
52         sort(d.begin(),d.end());
53         d.erase(unique(d.begin(),d.end()),d.end());
54         tot = (LL)d.size()-1;
55         for(LL i=0;i<n;i++){
56             if(s[i].ch==D){
57                 loc = lower_bound(d.begin(),d.end(),s[i].l) - d.begin();
58                 add(l,loc,1);
59                 loc = lower_bound(d.begin(),d.end(),s[i].r) - d.begin();
60                 add(r,loc,1);
61             }else if(s[i].ch==C){
62                 LL& e = N[s[i].k];
63                 loc = lower_bound(d.begin(),d.end(),s[e].l) - d.begin();
64                 add(l,loc,-1);
65                 loc = lower_bound(d.begin(),d.end(),s[e].r) - d.begin();
66                 add(r,loc,-1);
67 
68             }else{
69                 loc = lower_bound(d.begin(),d.end(),s[i].r) - d.begin();
70                 ans = query(l,loc);
71                 loc = lower_bound(d.begin(),d.end(),s[i].l) - d.begin();
72                 ans-= query(r,loc-1);
73                 cout<<ans<<endl;
74             }
75         }
76         //cout<<endl;
77     }
78     return 0;
79 }
Crayon

 

ACDream - Crayon,布布扣,bubuko.com

ACDream - Crayon

原文:http://www.cnblogs.com/sineatos/p/3861546.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!