zoukankan      html  css  js  c++  java
  • P2163 【[SHOI2007]园丁的烦恼】

    其实是不用把一个询问拆成四个的

    把询问转化为数学语言:

    对于每个查询,询问满足$a<=x<=b$且$c<=y<=d$的点$x,y$的个数

    ~~自然~~想到偏序问题,看到有两个式子,二维偏序?好像办不到,反正我不会

    如何升维,拆分即可

    把原式拆成$a<=x,x<=b,c<=y,y<=d$,这样就可以用四维偏序解决了,但是这样的复杂度显然是不能保证的

    尝试降维

    如果这样呢$a<=x,x<=b,c<=y<=d$

    对于一个点,我们定义其三个维度为:

    $a,b->x$即以横坐标作为第一维和第二维

    $c->y$即以纵坐标作为第三维

    而查询,依照上式,我们定义其维度

    以$a$为第一维,$c$为第二维,$b,d$为三维和四维(查询用)

    所以三维偏序的式子就是

    $a_i<=a_j,b_i>=b_j,c_i<=c_j<=d_i$

    考虑重复元素的贡献问题,记得排序时加上$c$相同,按$d$排

    上代码(其实是要写离散化的,但是我懒得写,拿$O2$替了)

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int maxn=5e5+10,maxl=1e7+10;
    struct node{
        int a,b,c,d,w,mp;
    }v[2*maxn];
    int n,m,c[maxl],ans[maxn];
    bool cmpy(const node &a,const node &b)
    {
        return a.b==b.b?(a.c==b.c?a.d<b.d:a.c>b.c):a.b<b.b;
    }
    bool cmpx(const node &a,const node &b)
    {
        return a.a==b.a?cmpy(a,b):a.a>b.a;
    }
    int lowbit(int x)
    {
        return x&-x;
    }
    void add(int x,int ch)
    {
        while(x<=maxl-9)
        {
            c[x]+=ch;
            x+=lowbit(x);
        }
    }
    int sum(int x)
    {
        int ret=0;
        while(x)
        {
            ret+=c[x];
            x-=lowbit(x);
        }
        return ret;
    }
    void cdq(int l,int r)
    {
        if(l==r)
            return;
        int mid=l+r>>1;
        cdq(l,mid),cdq(mid+1,r);
        sort(v+l,v+mid+1,cmpy),sort(v+mid+1,v+r+1,cmpy);
        int i=l,j=mid+1;
        for(;j<=r;j++)
        {
            while(v[i].b<=v[j].b&&i<=mid)
                add(v[i].c,v[i].w),i++;
            ans[v[j].mp]+=sum(v[j].d)-sum(v[j].c-1);
        }
        for(j=l;j<i;j++)
            add(v[j].c,-v[j].w);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&v[i].a,&v[i].c);
            v[i].a++,v[i].c++;
            v[i].b=v[i].a,v[i].w=1,v[i].d=v[i].mp=0;
        }
        for(int i=n+1;i<=n+m;i++)
        {
            scanf("%d%d%d%d",&v[i].a,&v[i].c,&v[i].b,&v[i].d);
            v[i].a++,v[i].b++,v[i].c++,v[i].d++;
            v[i].w=0,v[i].mp=i-n;
        }
        sort(v+1,v+n+m+1,cmpx);
        cdq(1,n+m);
        for(int i=1;i<=m;i++)
            printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    BugkuCtf-pwn2-exp
    Python 基础知识(一)
    C++基本语法的部分总结
    Ububtu 14.04 安装 Hadoop 2.7.3
    leetcode-Evaluate the value of an arithmetic expression in Reverse Polish Notation
    leetcode-Given a binary tree, find its minimum depth
    Java 实现 AES 加解密
    git fork代码并修改胡提交到自己的git仓库
    git使用记录_备忘
    java awt 中文乱码 显示为 方块
  • 原文地址:https://www.cnblogs.com/ivanovcraft/p/9826364.html
Copyright © 2011-2022 走看看