bzoj3262

树套树/CDQ分治

太弱了以至于不会写CDQ分治

这道题其实树套树还是很好写的

首先离线排序一维之后就变成二维偏序,就可以转换成平面单点+,询问矩阵和

/**************************************************************

    Problem: 3262

    User: syh0313

    Language: C++

    Result: Accepted

    Time:6624 ms

    Memory:236420 kb

****************************************************************/

 

#include <iostream>

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <string>

#include <cmath>

#include <algorithm>

#define lch a[n].lc

#define rch a[n].rc

using namespace std;

const int maxn=200010;

int n,t,root[5*maxn],topt,cnt,ans[maxn],ro;

struct da{int lc,rc,sum;}a[80*maxn];

struct daa{int lc,rc;}b[5*maxn];

struct daaa{int v,x,y;}q[maxn];

bool cmp(daaa aa,daaa bb){return aa.v<bb.v;}

inline void updata(int n){a[n].sum=a[lch].sum+a[rch].sum;}

void tree_add_2(int &n,int l,int r,int lc)

{

    if (!n) n=++topt;

    if (l==r) {a[n].sum++; return;}

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

    if (lc<=mid) tree_add_2(lch,l,mid,lc);else tree_add_2(rch,mid+1,r,lc);

    updata(n);

}

void tree_add(int &n,int l,int r,int lc,int y)

{

    if (!n) n=++cnt;

    tree_add_2(root[n],1,t,y);

    if (l==r) return;

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

    if (lc<=mid) tree_add(b[n].lc,l,mid,lc,y);

     else tree_add(b[n].rc,mid+1,r,lc,y);

}

int qury_2(int n,int L,int R,int l,int r)

{

    if (!n) return 0;

    if (L==l && R==r) return a[n].sum;

    int mid=(L+R)>>1;

    if (r<=mid) return qury_2(lch,L,mid,l,r);

    else if (l>=mid+1) return qury_2(rch,mid+1,R,l,r);

    else return qury_2(lch,L,mid,l,mid)+qury_2(rch,mid+1,R,mid+1,r);

}

int qury(int n,int L,int R,int l,int r,int y1,int y2)

{

    if (!n) return 0;

    if (L==l && R==r) return qury_2(root[n],1,t,y1,y2);

    int mid=(L+R)>>1;

    if (r<=mid) return qury(b[n].lc,L,mid,l,r,y1,y2);

    else if (l>=mid+1) return qury(b[n].rc,mid+1,R,l,r,y1,y2);

return qury(b[n].lc,L,mid,l,mid,y1,y2)+qury(b[n].rc,mid+1,R,mid+1,r,y1,y2);

}

struct fastio{

    static const int s=1<<24;

    int wp,p,l;char bf[s];

    fastio(){wp=p=l=0;}

    char gc(){

        static char bf[s];

        if(p==l)p=0,l=fread(bf,1,s,stdin);

        return p==l?-1:bf[p++];

    }

    bool read(int&x){

        char c=gc();x=0;

        while((c<'0'||c>'9')&&~c)c=gc();

        if(c==-1)return 0;

        for(;c>='0'&&c<='9';c=gc())x=x*10+c-'0';

        return 1;

    }

}io;

int main()

{  

    io.read(n); io.read(t); register int i,k;

    for (i=1;i<=n;i++) io.read(q[i].v),io.read(q[i].x),io.read(q[i].y);

    sort(q+1,q+n+1,cmp);

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

    {

        int j=i; tree_add(ro,1,t,q[i].x,q[i].y);

        while (q[j+1].v==q[i].v && j+1<=n)

         {tree_add(ro,1,t,q[j+1].x,q[j+1].y); j++;}

        for (k=i;k<=j;k++) ans[qury(ro,1,t,1,q[k].x,1,q[k].y)-1]++;

        i=j;

    }

    for (i=0;i<n;i++) printf("%d\n",ans[i]);

return 0;  

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值