CDQ partition && whole dichotomy

The following reference information from Owen_codeisking Gangster blog

A, \ (the CDQ \) Divide and Conquer

First, I recommend that you look at a tree little friends to the front of an array and knowledge divide and conquer

1. The two-dimensional partial ordering

Title: [template] two-dimensional partial order && HDU1541 Stars

Two-dimensional partial ordering problem: you \ (n-\) points, and this \ (n-\) th point coordinates \ (X_ {i} \) and \ (Y_ {I} \) , so \ (F {i } = X {j} \ le X {i} and Y {j} \ le Y { i} \) the number of points, find the \ (F {i} \)

This view, of course, can use violent solution, the most violent of up to \ (O (n ^ 2) \) time complexity, but only in \ (n \ le5000 \) with time

But if \ (10000 \ le n \) it?

Perhaps you have \ (n ^ 2 \) millions of experience (it is because you are a Gangster), but here we will introduce a \ (O (nlogn) \) algorithm: \ (the CDQ \) Divide and Conquer the most basic use

We put this question as a map (stolen)
Here Insert Picture Descriptionthen point the figure circled top right corner of the rectangle is to meet the conditions of point

First, we first point ordinate \ (y {i} \) in ascending order (sort abscissa or ordinate see mood (just)), that with a \ (Sort \) can be achieved

Next, we ensure that the \ (y {i} \) of the small to large, the abscissa begins to sort

This sorting operation can be achieved with Fenwick tree

int c[N];
void add(int x,int y)
{
    for(;x<=N;x+=lowbit(x))c[x]+=y;
}
int sum(int x)
{
    int ans=0;
    for(;x>0;x-=lowbit(x))ans+=c[x];
    return ans;
}

This is the Fenwick tree template, not much talk

#include<bits/stdc++.h>
using namespace std;
# define lowbit(x) ((x)&(-(x))) 
# define int long long 
const int N=100010;
int n;
struct edge
{
    int a,b;
}p[N];
int c[N];
bool cmp(edge a,edge b)
{
    if(a.a==b.a)return a.b<b.b;
    return a.a<b.a;
}
int sum(int x)//从大往小搜索
{
    int ans=0;
    for(;x;x-=lowbit(x))ans+=c[x];
    return ans;
}
void add(int x,int y)
{
    for(;x<N;x+=lowbit(x))c[x]+=y;
}
signed main()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)scanf("%lld %lld",&p[i].a,&p[i].b);
    sort(p+1,p+n+1,cmp);
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        int now=sum(p[i].b+1);//这就是f[i]的值
        ans+=now;
        add(p[i].b+1,1);
    }
    printf("%lld",ans);
    return 0;
}

2. The three-dimensional partial ordering

Topic: P3810 [template] three-dimensional partial order (Mo flowers)

This is a two-dimensional partial ordering pay more in one dimension, from the original condition \ (X {j} \ le X {i} and Y {j} \ le Y { i} \) increased \ (X {j} \ le X {i} and Y {j} \ le Y { i} and Z {j} \ le Z { i} \)

At this point, we press the abscissa sorting, satisfies the first condition dimension

Then, we meet with a second dimension merge sort conditions

Fenwick tree and then meet the conditions of the third dimension

Here we take a detailed look at merge sort

When we merge, to consider the interval (\ [l, mid]) \ on the interval \ ([mid + 1, r ] \) contribution, because we have satisfied the first condition dimension to sort through, so no matter how broken, \ ([l, mid] \ ) number of all sections are less \ ([mid + 1, r ] \) of the number of

We first set up a structure

struct edge
{
    int a,b,c,re,ans;//re表示与e[i]重复的点的个数,ans表示对于i满足条件的节点个数
}e[N],t[N];
Merge, by definition, recursive merge sort, therefore, need to implement the merger by recursion.
    if(l==r)return ;
    int mid=(l+r)>>1;
    cdq(l,mid);cdq(mid+1,r);

I believe the above code is well understood

Heavy and difficult: to knock blackboard

Here Insert Picture Description
Next, we need to respectively traverse the interval \ ([l, mid] \ ) , and the interval \ ([mid + 1, r ] \) numbers and compared with one another
we set the interval \ ([l, mid] \ ) traversal to the point \ (P \) , the interval \ ([mid + 1, r ] \) is from \ (Q \) , a structure is provided in \ (T \) changed dot sequential storage.

  1. If \ (P \) is less than a second dimension equal to \ (Q \) in the second dimension
    then the first and second dimensions are met, directly satisfy the third tree-dimensional array, the update \ (T \) , and next continue to traverse a \ (p \)
  2. If a condition is not satisfied, then \ (ANS \) update, with respect to \ (Q \) number of nodes of the condition is satisfied, and updates \ (T \) , and continues to traverse the next \ (Q \)
    while(p<=mid&&q<=r)
    {
        if(e[p].b<=e[q].b)add(e[p].c,e[p].re),t[tot++]=e[p++];
        else e[q].ans+=sum(e[q].c),t[tot++]=e[q++];
    } 

In \ (the while \) after, not a little fear traversed, then the current from the \ (P \) traversed \ (MID \) , from \ (mid + 1 \) to \ (Q \) , the operation codes are the same as above

    while(p<=mid)add(e[p].c,e[p].re),t[tot++]=e[p++];
    while(q<=r)e[q].ans+=sum(e[q].c),t[tot++]=e[q++];

The last reduction Fenwick tree, because we are just to update \ (t \) array, in order to operate after the implementation needs to be restored

And (T \) \ copied to the current structure

    for(int i=l;i<=mid;i++)add(e[i].c,-e[i].re);
    for(int i=l;i<=r;i++)e[i]=t[i];

The entire code is (I know you just look at this)

#include<bits/stdc++.h>
#define lowbit(x) ((x)&(-(x)))
#define N 100010
using namespace std;
int n,m;
int output[N];
int c[N];
struct edge
{
    int a,b,c,re,ans;
}e[N],t[N];
bool cmp(edge a,edge b)
{
    if(a.a!=b.a)return a.a<b.a;
    if(a.b!=b.b)return a.b<b.b;
    return a.c<b.c;
}
void add(int x,int y)
{
    for(;x<=m;x+=lowbit(x))c[x]+=y;
}
int sum(int x)
{
    int ans=0;
    for(;x;x-=lowbit(x))ans+=c[x];
    return ans;
}
void cdq(int l,int r)
{
    if(l==r)return ;
    int mid=(l+r)>>1;
    cdq(l,mid);cdq(mid+1,r);
    int p=l,q=mid+1,tot=l;
    while(p<=mid&&q<=r)
    {
        if(e[p].b<=e[q].b)add(e[p].c,e[p].re),t[tot++]=e[p++];
        else e[q].ans+=sum(e[q].c),t[tot++]=e[q++];
    } 
    while(p<=mid)add(e[p].c,e[p].re),t[tot++]=e[p++];
    while(q<=r)e[q].ans+=sum(e[q].c),t[tot++]=e[q++];
    for(int i=l;i<=mid;i++)add(e[i].c,-e[i].re);
    for(int i=l;i<=r;i++)e[i]=t[i];
}
int main()
{
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d %d %d",&e[i].a,&e[i].b,&e[i].c);
        e[i].re=1;
    }
    sort(e+1,e+n+1,cmp);
    int cnt=1;
    for(int i=2;i<=n;i++)
    {
        if(e[cnt].a==e[i].a&&e[cnt].b==e[i].b&&e[cnt].c==e[i].c)e[cnt].re++;
        else e[++cnt]=e[i];
    }
    cdq(1,cnt);
    for(int i=1;i<=cnt;i++)output[e[i].ans+e[i].re-1]+=e[i].re;
    for(int i=0;i<n;i++)printf("%d\n",output[i]);
    return 0;
}

tips: Because the P3810 [template] three-dimensional partial order (Mo flowers), it is possible to duplicate spots appear, we need to re-sentence

  1. Dimensional partial ordering

Too sick, konjac yet does not want to know can take a look at the top of the reference blog blog

Second, the overall half

Guess you like

Origin www.cnblogs.com/ShuraEye/p/11354541.html