Acdream1157---Segments (CDQ分治)

陈丹琦分治~~~其实一些数据小的时候可以用二维或者多维树状数组做的,而数据大的时候就无力的题目,都可以用陈丹琦分治解决。

题目:由3钟类型操作:
1)D L R(1 <= L <= R <= 1000000000) 增加一条线段[L,R]
2)C i (1-base) 删除第i条增加的线段,保证每条插入线段最多插入一次,且这次删除操作一定合法
3) Q L R(1 <= L <= R <= 1000000000) 查询目前存在的线段中有多少条线段完全包含[L,R]这个线段,线段X被线段Y完全包含即LY <= LX

<= RX <= RY)
给出N,接下来N行,每行是3种类型之一

 

由于 L R 比较大,直接是不行的,于是我们可以利用CDQ分治把二维变成一维,然后离散化。树状数组查询。

对于询问 L R 只需要 知道 小于等于L 且大于等于R的有多少个就可以了。这里我是把线段左端点进行CDQ分治,然后每次查询大于R数目。

  1 #include <cstdio>

  2 #include <string>

  3 #include <vector>

  4 #include <cstdlib>

  5 #include <cstring>

  6 #include <iostream>

  7 #include <algorithm>

  8 using namespace std;

  9 const int maxn = 1e5+10;

 10 struct Node

 11 {

 12     int idx,l,r,delt;

 13     int kind;

 14     bool operator < (const Node &rhs)const

 15     {

 16         return l < rhs.l ;

 17     }

 18 }node[maxn];

 19 int ans[maxn],del[maxn];

 20 //-------------BIT---------       //此处树状数组反向写的,用于查询 大于等于x的数有多少个

 21 inline int lowbit (int x)

 22 {

 23     return x & -x;

 24 }

 25 int arr[maxn],MAX;

 26 void add (int x,int d)

 27 {

 28     while (x)

 29     {

 30         arr[x] += d;

 31         x -= lowbit(x);

 32     }

 33 }

 34 int sum(int x)

 35 {

 36     int ans = 0;

 37     while (x <= MAX)

 38     {

 39         ans += arr[x];

 40         x += lowbit(x);

 41     }

 42     return ans;

 43 }

 44 //--------------离散化-----

 45 int vec[maxn],vec_idx;

 46 int hash_(int x)

 47 {

 48     return lower_bound(vec,vec+vec_idx,x) - vec + 1;

 49 }

 50 //------------------------

 51 void CDQ(int l,int r)

 52 {

 53     if (l == r)

 54         return;

 55     int mid = (l + r) >> 1;

 56     CDQ(l,mid);

 57     CDQ(mid+1,r);

 58     int j = l;

 59     for (int i = mid+1; i <= r; i++)

 60     {

 61         if (node[i].kind == 2)

 62         {

 63             for ( ;j <= mid && node[j].l <= node[i].l; j++)

 64             {

 65                 if (node[j].kind == 1)

 66                 {

 67                     add(hash_(node[j].r),node[j].delt);

 68                 }

 69             }

 70             ans[node[i].idx] += sum(hash_(node[i].r));

 71         }

 72     }

 73     for (int i = l; i < j; i++)

 74         if ( node[i].kind == 1)

 75             add(hash_(node[i].r),-node[i].delt);

 76     inplace_merge(node+l,node+mid+1,node+r+1);

 77 }

 78 int vis[maxn];

 79 int main(void)

 80 {

 81     #ifndef ONLINE_JUDGE

 82         freopen("in.txt","r",stdin);

 83     #endif

 84     int n;

 85     while (~scanf ("%d",&n))

 86     {

 87         int cnt = 0;

 88         vec_idx = 0;

 89         memset(arr,0,sizeof(arr));

 90         memset(ans,0,sizeof(ans));

 91         memset(vis,0,sizeof(vis));

 92         vector<int>vv;

 93         for (int i = 1; i <= n; i++)

 94         {

 95             char op[3];

 96             scanf ("%s",op);

 97             if (op[0] == 'D')

 98             {

 99                 scanf ("%d%d",&node[i].l,&node[i].r);

100                 node[i].kind = 1;

101                 node[i].idx = i;

102                 node[i].delt = 1;

103                 vec[vec_idx++] = node[i].r;

104                 vv.push_back(i);

105             }

106             if (op[0] == 'Q')

107             {

108                 scanf ("%d%d",&node[i].l,&node[i].r);

109                 node[i].kind = 2;

110                 node[i].idx = i;

111                 vec[vec_idx++] = node[i].r;

112                 vis[i] = 1;

113             }

114             if (op[0] == 'C')

115             {

116                 int tmp;

117                 scanf ("%d",&tmp);

118                 node[i].kind = 1;

119                 node[i].l = node[vv[tmp-1]].l;

120                 node[i].r = node[vv[tmp-1]].r;

121                 node[i].delt = -1;                    // 对于删除的边类型与增加的相同但是,操作的时候是-1

122                 node[i].idx = i;

123             }

124         }

125         sort(vec,vec+vec_idx);

126         vec_idx = unique(vec,vec+vec_idx) - vec;

127         MAX = vec_idx + 10;

128         CDQ(1,n);

129         for (int i = 1; i <= n; i++)

130         {

131             if (vis[i])

132                 printf("%d\n",ans[i]);

133         }

134     }

135     return 0;

136 }

 

你可能感兴趣的:(cd)