zoukankan      html  css  js  c++  java
  • bzoj3262陌上花开 (CDQ,BIT)

    题目大意
    bzoj

    给定n朵花,每个花有三个属性,定义(f[i])为满足(a_j le a_i)(b_j le b_i)(c_j le c_i)的j的数量,
    (d in [0,n)),(f[i]=d)的数量

    这题是一道CDQ的入门题

    CDQ其实本质上是一个分治的过程,需要将询问离线,然后进行分治
    一般都是:

    if (l==r) return;
    cdq(l,mid);
    cdq(mid+1,r);
    处理左半区间对右半区间的影响
    

    对于这个题,有三维,首先对于第一维进行排序去重,然后进行CDQ,递归到一层,分别对([l,mid])([mid+1,r])分别进行第二维的排序,然后用树状数组统计左边区间对右边区间影响(就是求满足(b_i<b_j)的顺序对个数)
    具体实现就是两个指针,一个从l开始跳,一个从mid+1开始循环,因为要统计左半区间对右边的影响,所以二者的循环上界也是要有限制的
    具体可以看一下代码

        int pos = l;
        for (int i=mid+1;i<=r;i++)
        {
            while (b[pos].b<=b[i].b && pos<=mid) modify(b[pos].c,b[pos].cnt),pos++;
            b[i].ans+=query(b[i].c);
        }
        for (int i=l;i<pos;i++) modify(b[i].c,-b[i].cnt);
    

    最后统计的答案的时候注意:

    for (int i=1;i<=tot;i++) ans[b[i].ans+b[i].cnt-1]+=b[i].cnt;
    

    这里加(b[i].cnt-1),是因为要统计 (le) 而不是 (<)

    上总的代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<queue>
    #include<map>
    #include<vector>
    
    using namespace std;
    
    inline int read()
    { 
      int x=0,f=1;char ch=getchar();while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
      while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;
    }
    
    const int maxn = 2e5+1e2;
    
    struct Node{
        int a,b,c,cnt,ans;
    };
    Node a[maxn];
    Node b[maxn];
    int ans[maxn];
    int c[maxn];
    int n,maxval;
    int tot;
    int lowbit(int x){return x&(-x);}
    void modify(int x,int p){for (int i=x;i<=maxval;i+=lowbit(i)) c[i]+=p;}
    int query(int x){int ans=0; for (int i=x;i;i-=lowbit(i)) ans+=c[i]; return ans;}
    bool cmp1(Node a,Node b)
    {
        if (a.a==b.a){
            if (a.b==b.b) return a.c<b.c;else return a.b<b.b;
        }return a.a<b.a;
    }
    bool cmp2(Node a,Node b){
      if (a.b==b.b){return a.c<b.c;}
      return a.b<b.b;
    }
    void cdq(int l,int r)
    {
        if (l==r) return;
        int mid = (l+r) >> 1;
        cdq(l,mid);cdq(mid+1,r);
        sort(b+l,b+mid+1,cmp2);
        sort(b+mid+1,b+r+1,cmp2);
        int pos = l;
        for (int i=mid+1;i<=r;i++)
        {
            while (b[pos].b<=b[i].b && pos<=mid) modify(b[pos].c,b[pos].cnt),pos++;
            b[i].ans+=query(b[i].c);
        }
        for (int i=l;i<pos;i++) modify(b[i].c,-b[i].cnt);
    }
    int main()
    {
      scanf("%d%d",&n,&maxval);
      for (int i=1;i<=n;i++) scanf("%d%d%d",&a[i].a,&a[i].b,&a[i].c);
      sort(a+1,a+1+n,cmp1);
      for (int i=1;i<=n;i++)
      {
      	if (a[i].a==a[i-1].a && a[i].b==a[i-1].b && a[i].c==a[i-1].c) b[tot].cnt++;
      	else b[++tot]=a[i],b[tot].cnt=1;
      }
      cdq(1,tot);
      for (int i=1;i<=tot;i++) ans[b[i].ans+b[i].cnt-1]+=b[i].cnt;
      for (int i=0;i<n;i++) printf("%d
    ",ans[i]);
      return 0;
    }
    
  • 相关阅读:
    翻译:《实用的Python编程》03_04_Modules
    翻译:《实用的Python编程》03_03_Error_checking
    翻译:《实用的Python编程》03_02_More_functions
    翻译:《实用的Python编程》03_01_Script
    翻译:《实用的Python编程》03_00_Overview
    翻译:《实用的 Python 编程》02_07_Objects
    翻译:《实用的Python编程》02_06_List_comprehension
    生成器
    python编码
    python迭代器
  • 原文地址:https://www.cnblogs.com/yimmortal/p/10160717.html
Copyright © 2011-2022 走看看