P2184 【贪婪大陆】

看到全是线段树或者树状数组写法,就来提供一发全网唯一cdq分治三维偏序解法吧

容易发现,这个题的查询就是对于每个区间l,r,查询有多少个修改区间li,ri与l,r有交集

转化为数学语言,就是查询满足li<=r且ri>=l的修改个数

一个二维偏序问题,但是我们发现,这是个动态插入的二维偏序问题

_(:з」∠)_一时不知所措

再想一想,不妨把时间另开一个维度作为第三维,然后就是这样了

对于每个查询,我们要求出它之前有多少个修改区间与其相交

数学语言:

查询满足li<=r且ri>=l且[li,ri].time<[l,r].time的修改个数

思路清晰明了,而且敲好想,但是实现细节还是比较麻烦的(一部分是因为我的奇葩cdq写法),在代码注释里解释一下(模板这种的就不解释了)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=1e5+10;
struct node{
    int a,b,c,q,w;
//a,b,c表示三个维度,q记录这个操作是修改还是查询
//w表示这个是否有效(和q差不多,查询是不需要统计的,w=0;修改的w=1)
}v[maxn];
int n,m,cnt,tot,c[maxn],ans[maxn];
bool vis[maxn];
bool cmpx(const node &a,const node &b)
{
    return a.a==b.a?(a.b==b.b?a.c<b.c:a.b<b.b):a.a<b.a;
}
bool cmpy(const node &a,const node &b)
{
    return a.b==b.b?a.c<b.c:a.b<b.b;
}
int lowbit(int x)
{
    return x&-x;
}
void add(int x,int ch)
{
    while(x<=n)
    {
        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++;
        if(v[j].q==2)
            ans[v[j].a]+=sum(n)-sum(v[j].c-1);
            //统计贡献到ans数组中
    }
    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<=m;i++)
    {
        scanf("%d%d%d",&v[i].q,&v[i].b,&v[i].c);
        v[i].w=1;
        if(v[i].q==2)
            swap(v[i].b,v[i].c),v[i].w=0,vis[i]=1;
            //标记每个操作是否需要输出
        v[i].a=i;
    }
    cdq(1,m);
    //枚举每个操作,需要输出就输出
    for(int i=1;i<=m;i++)
        if(vis[i])
            printf("%d\n",ans[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/ivanovcraft/p/9692861.html

时间: 2024-10-10 10:22:10

P2184 【贪婪大陆】的相关文章

P2184 贪婪大陆

P2184 贪婪大陆 题目背景 面对蚂蚁们的疯狂进攻,小FF的Tower defence宣告失败……人类被蚂蚁们逼到了Greed Island上的一个海湾.现在,小FF的后方是一望无际的大海, 前方是变异了的超级蚂蚁. 小FF还有大好前程,他可不想命丧于此, 于是他派遣手下最后一批改造SCV布置地雷以阻挡蚂蚁们的进攻. 题目描述 小FF最后一道防线是一条长度为N的战壕, 小FF拥有无数多种地雷,而SCV每次可以在[ L , R ]区间埋放同一种不同于之前已经埋放的地雷. 由于情况已经十万火急,小

[洛谷P2184]贪婪大陆

题目大意:有n个点,每次在l~r之间所有点各加上同一种地雷,或询问某一区间内地雷种数. 解题思路:首先注意是“加上”而不是“覆盖”. 然后我们用两棵线段树(树状数组),一棵维护某一区间内左端点个数,另一棵维护右端点个数. 由于每次只加上一个端点,故为单点修改. 那么如何查询呢? 如果1~r内有a个左端点,则说明最多有a种地雷,如果1~l-1内有b个右端点,则说明a种地雷中,有b种的右端点没有达到l(否则一定在l-1之后). 那么查询出a和b,然后输出a-b即可. 很明显是区间修改. 时间复杂度$

Luogu P2184 贪婪大陆

线段树 我居然想了一个半小时才想出来 读完题可以发现如果布不同地雷的区间如果相交的话,地雷是不会覆盖的 两种不同的地雷会共存在一格中 那么在问题可以转化,所求答案就是当前询问的区间与之前布地雷的区间有多少个相交或包含 (我没想到) 那么考虑一个区间不与另一个区间相交的条件 即$r_{1}<l_{2}$或$l_{1}>r_{2}$ 那么可以用线段树维护对于每个点区间右端点小于等于这点的区间数量$s1$,和左端点大于等于这点的区间数量$s2$ 那么询问时答案就是当前布地雷的总数量减去$s1[l-1

luoguP2184 贪婪大陆 题解(树状数组)

P2184 贪婪大陆  题目 其实很容易理解就是询问一段区间内有多少段不同的区间 然后再仔细思索一下会发现: 1.只要一个区间的开头在一个节点i的左边,那么这个区间包含在区间1~i中. 2.只要一个区间的尾部在一个节点j的左边,那么这个区间肯定不属于j之后的所有区间 这时候就不难想到用两个树状数组维护: 第一个:维护节点i之前有多少个区间的开头 第二个:维护节点j之前有多少个区间的结尾 不难证明拿sum[i]-sum[j]得到的就是i~j中间地雷的个数(手动模拟一波就一清二楚了) #includ

AC日记——贪婪大陆 洛谷 P2184

贪婪大陆 思路: 树状数组: 跪烂.. 代码: #include <bits/stdc++.h> using namespace std; #define maxn 100005 int n,m,ltree[maxn],rtree[maxn],tot; inline void in(int &now) { char Cget=getchar();now=0; while(Cget>'9'||Cget<'0')Cget=getchar(); while(Cget>='0

cogs——1008. 贪婪大陆(清华巨佬代码)——树状数组

1008. 贪婪大陆 ★★   输入文件:greedisland.in   输出文件:greedisland.out   简单对比时间限制:1 s   内存限制:128 MB 试题四:贪婪大陆  [题目描述]  面对蚂蚁们的疯狂进攻,小FF的Tower defense宣告失败……人类被蚂蚁们逼到了Greed Island上的一个海湾.现在,小FF的后方是一望无际的大海,前方是变异了的超级蚂蚁. 小FF还有大好前程,他可不想命丧于此, 于是他派遣手下最后一批改造SCV布置地雷以阻挡蚂蚁们的进攻. 

COGS1008. 贪婪大陆[树状数组 模型转换]

1008. 贪婪大陆 ★★   输入文件:greedisland.in   输出文件:greedisland.out   简单对比时间限制:1 s   内存限制:128 MB 试题四:贪婪大陆  [题目描述]  面对蚂蚁们的疯狂进攻,小FF的Tower defense宣告失败……人类被蚂蚁们逼到了Greed Island上的一个海湾.现在,小FF的后方是一望无际的大海,前方是变异了的超级蚂蚁. 小FF还有大好前程,他可不想命丧于此, 于是他派遣手下最后一批改造SCV布置地雷以阻挡蚂蚁们的进攻. 

luogu题解 P2184 【贪婪大陆】

题目链接: https://www.luogu.org/problemnew/show/P2184 思路: 首先我想吐槽一下为什么现有题解中的做法都是一样的,而且还比较难以理解; 我就讲下我的做法,本质上是一样的,但是跟容易理解. 根据题意每加一次地雷就多一个种类对吧,我们用一个cnt记录加过地雷的次数,同时分别用两个数组记录左右两个端点的位置.然后查询[l,r]时呢,我们分别查询[1,l-1]有多少个右端点,[r+1,n]有多少个左端点,然后这两个数的和是什么意思呢?就是有多少次铺地雷没铺到我

贪婪大陆

题目背景 面对蚂蚁们的疯狂进攻,小FF的Tower defence宣告失败--人类被蚂蚁们逼到了Greed Island上的一个海湾.现在,小FF的后方是一望无际的大海, 前方是变异了的超级蚂蚁. 小FF还有大好前程,他可不想命丧于此, 于是他派遣手下最后一批改造SCV布置地雷以阻挡蚂蚁们的进攻. 题目描述 小FF最后一道防线是一条长度为N的战壕, 小FF拥有无数多种地雷,而SCV每次可以在[ L , R ]区间埋放同一种不同于之前已经埋放的地雷. 由于情况已经十万火急,小FF在某些时候可能会询