• 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
    ",ans[i]);
    133         }
    134     }
    135     return 0;
    136 }
  • 相关阅读:
    转ANYTAO的学习方法
    第一次写文章
    分享一个有趣的学习方法,欢迎一起探讨如何提高学习兴趣
    SQL基础
    insert into 后获得自动插入的id(select @@identity)
    如何向ASP.NET Web 服务器控件添加客户端脚本事件
    关键字using的主要用途
    网页设计师必备的10个CSS技巧
    DataSet与DataReader的区别
    由于系统时间修改导致Oracle启动失败
  • 原文地址:https://www.cnblogs.com/oneshot/p/4143950.html
Copyright © 2020-2023  润新知