bzoj4822: [Cqoi2017]老C的任务(扫描线+BIT/线段树)

  裸题...

  依旧是写了BIT和线段树两种(才不是写完线段树后才想起来可以写BIT呢

  怎么卡常数都挺大...QAQ ccz和yy的写法好快哇

BIT:

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<map>
#define ll long long
using namespace std;
const int maxn=500010,inf=1e9;
struct poi{int fir,sec,trd,ty,pos,w;}a[maxn];
int n,m,x,y,z,cnt,N,x1,x2,y1,y2;
int b[maxn];
ll tree[maxn],ans[maxn];
void read(int &k)
{
    int f=1;k=0;char c=getchar();
    while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar();
    while(c<=‘9‘&&c>=‘0‘)k=k*10+c-‘0‘,c=getchar();
    k*=f;
}
inline bool cmp(poi a,poi b){return a.fir==b.fir?a.ty<b.ty:a.fir<b.fir;}
inline int lowbit(int x){return x&-x;}
inline void add(int x,int delta){for(;x<=N;x+=lowbit(x))tree[x]+=delta;}
inline ll query(int x){ll sum=0;for(;x;x-=lowbit(x))sum+=tree[x];return sum;}
int main()
{
    read(n);read(m);cnt=n;
    for(int i=1;i<=n;i++)
    {
        read(x);read(y);read(z);
        a[i].fir=x;a[i].sec=y;a[i].w=z;b[++N]=y;
    }
    for(int i=1;i<=m;i++)
    {
        read(x1);read(y1);read(x2);read(y2);
        a[++cnt].fir=x1;a[cnt].sec=y1;a[cnt].trd=y2;a[cnt].ty=-1;a[cnt].pos=i;
        a[++cnt]=a[cnt-1];a[cnt].fir=x2;a[cnt].ty=1;b[++N]=y1;b[++N]=y2;
    }
    sort(b+1,b+1+N);
    for(int i=1;i<=n;i++)a[i].sec=lower_bound(b+1,b+1+N,a[i].sec)-b;
    for(int i=n+1;i<=cnt;i+=2)
    {
        a[i].sec=a[i+1].sec=lower_bound(b+1,b+1+N,a[i].sec)-b;
        a[i].trd=a[i+1].trd=lower_bound(b+1,b+1+N,a[i].trd)-b;
    }
    sort(a+1,a+1+cnt,cmp);
    for(int i=1;i<=cnt;i++)
    {
        if(a[i].ty)
        {
            ll sum=query(a[i].trd)-query(a[i].sec-1);
            ans[a[i].pos]+=(a[i].ty==1?sum:-sum);
        }
        else add(a[i].sec,a[i].w);
    }
    for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);
    return 0;
}

线段树:

#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<map>
#define ll long long
using namespace std;
const int maxn=500010,inf=1e9;
struct poi{int fir,sec,trd,ty,pos,w;}a[maxn];
int n,m,x,y,z,cnt,N,x1,x2,y1,y2;
int b[maxn];
ll tree[maxn*4],ans[maxn];
void read(int &k)
{
    int f=1;k=0;char c=getchar();
    while(c<‘0‘||c>‘9‘)c==‘-‘&&(f=-1),c=getchar();
    while(c<=‘9‘&&c>=‘0‘)k=k*10+c-‘0‘,c=getchar();
    k*=f;
}
inline bool cmp(poi a,poi b){return a.fir==b.fir?a.ty<b.ty:a.fir<b.fir;}
inline void pushup(int x){tree[x]=tree[x<<1]+tree[x<<1|1];}
inline void add(int x,int l,int r,int cx,int delta)
{
    if(l==r){tree[x]+=delta;return;}
    int mid=(l+r)>>1;
    if(cx<=mid)add(x<<1,l,mid,cx,delta);
    else add(x<<1|1,mid+1,r,cx,delta);
    pushup(x);
}
inline ll query(int x,int l,int r,int cl,int cr)
{
    if(cl<=l&&r<=cr)return tree[x];
    int mid=(l+r)>>1;ll ret=0;
    if(cl<=mid)ret+=query(x<<1,l,mid,cl,cr);
    if(cr>mid)ret+=query(x<<1|1,mid+1,r,cl,cr);
    return ret;
}
int main()
{
    read(n);read(m);cnt=n;
    for(int i=1;i<=n;i++)
    {
        read(x);read(y);read(z);
        a[i].fir=x;a[i].sec=y;a[i].w=z;b[++N]=y;
    }
    for(int i=1;i<=m;i++)
    {
        read(x1);read(y1);read(x2);read(y2);
        a[++cnt].fir=x1;a[cnt].sec=y1;a[cnt].trd=y2;a[cnt].ty=-1;a[cnt].pos=i;
        a[++cnt]=a[cnt-1];a[cnt].fir=x2;a[cnt].ty=1;b[++N]=y1;b[++N]=y2;
    }
    sort(b+1,b+1+N);
    for(int i=1;i<=n;i++)a[i].sec=lower_bound(b+1,b+1+N,a[i].sec)-b;
    for(int i=n+1;i<=cnt;i+=2)
    {
        a[i].sec=a[i+1].sec=lower_bound(b+1,b+1+N,a[i].sec)-b;
        a[i].trd=a[i+1].trd=lower_bound(b+1,b+1+N,a[i].trd)-b;
    }
    sort(a+1,a+1+cnt,cmp);
    for(int i=1;i<=cnt;i++)
    {
        if(a[i].ty)
        {
            ll sum=query(1,1,N,a[i].sec,a[i].trd);
            ans[a[i].pos]+=(a[i].ty==1?sum:-sum);
        }
        else add(1,1,N,a[i].sec,a[i].w);
    }
    for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);
    return 0;
}

时间: 2024-10-10 22:52:57

bzoj4822: [Cqoi2017]老C的任务(扫描线+BIT/线段树)的相关文章

bzoj4822: [Cqoi2017]老C的任务

4822: [Cqoi2017]老C的任务 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 284  Solved: 152[Submit][Status][Discuss] Description 老 C 是个程序员. 最近老 C 从老板那里接到了一个任务--给城市中的手机基站写个管理系统.作为经验丰富的程序员,老 C 轻松 地完成了系统的大部分功能,并把其中一个功能交给你来实现.由于一个基站的面积相对于整个城市面积来说非常 的小,因此每个的基站

Atlantis HDU - 1542 (扫描线,线段树)

扫描线的模板题,先把信息接收,然后排序,记录下上边和下边,然后用一条虚拟的线从下往上扫.如果我扫到的是下边,那么久用线段树在这个区间内加上1,表示这个区间现在是有的,等我扫描到上边的时候在加上-1,把之前的消掉,然后线段树维护区间内的长度,这里不是直接用下标维护,而是需要另一个数组来维护,每次记录我当前的下标在原本的图中的长度. 在update部分用一个点表示我这个点以后的一个长度为1的区间,然后这样算出来的sum[1]就是我现在线段树里包括的区间大小,然后用现在的区间大小去乘上这一部分的高度,

HDU - 1542 扫描线入门+线段树离散化

扫描线算法+线段树维护简介: 像这种求面积的并集的题目,就适合用扫描线算法解决,具体来说就是这样 类似这种给出点的矩形的对角的点的坐标,然后求出所有矩形面积的交集的问题,可以采用扫描线算法解决.图如下,我们要求红色部分的面积: 我们可以通过一条叫扫描线的东西解决问题.具体来说: 我们首先给自己一条线,这条可以我称之为标准线(棕色线表示) 从上往下(从下往上也行)我们把每个矩形用一个四元组表示了l,r,h,f  也就是说,把一个矩形用上下两条边表示,l,r分别是x1,x2,而h则是y坐标,f代表这

扫描线,线段树,离散化——HDU - 1542

题目含义 每一行给出两个点,代表一个矩形的左下角端点和右上角端点 要你求出这些矩形覆盖坐标轴的整个面积 题目分析 用平行x轴的扫描线扫描整个图形,得到很多长宽不同的矩形,求出面积再相加 将每个矩形的面积记作 len(x)*len(y) 每个len(x)我们通过加减每个点的x左右坐标,通过线段树求sum[1]得到 每个len(y)我们通过这个点与下一个点的y坐标的差得到 所以我们要把所有点按y轴大小排序,并且记录每个点的左右x轴坐标 注意:这里用的线段树sum[l,r]不是指区间[l,r]的和,而

CF538H Summer Dichotomy 二分图、扫描线、线段树

标算太NB 我觉得用这种做法,这道题难度只有2500 如果原图不是二分图显然无解.否则对于一个点数\(\geq 2\)的连通块的两边可以缩成两个点,它们不能染相同的颜色.对于独立的点可以新建一个\([0,10^9]\)的虚点让这个点和虚点不染相同颜色.然后就变成了有\(n\)个区间.\(\frac{n}{2}\)对限制,每个区间仅在一对限制中. 枚举颜色\(1\)中所有区间的交,这样对于每一对限制连接的两个区间就会有一些限制. 举个栗子:对于限制\([l_1,r_1],[l_2,r_2]\),假

[HDOJ1828]Picture(扫描线,线段树,矩形并周长)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1828 题意:求矩形并的周长. 很好发现一个规律,那就是扫描到当前状态,update之后的线段树中线段的长度减去update之前的长度差的绝对值恰好是当前段并后的水平或者垂直的线段长度. 那么..存两棵线段树,横着扫一遍竖着扫一遍,加起来就行了.. 竟然没MLE... 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define lrt

51nod 1206 &amp;&amp; hdu 1828 Picture (扫描线+离散化+线段树 矩阵周长并)

1206 Picture  题目来源: IOI 1998 基准时间限制:2 秒 空间限制:131072 KB 分值: 160 难度:6级算法题  收藏  关注 给出平面上的N个矩形(矩形的边平行于X轴和Y轴),求这些矩形组成的所有多边形的周长之和. 例如:N = 7.(矩形会有重叠的地方). 合并后的多边形: 多边形的周长包括里面未覆盖部分方块的周长. Input 第1行:1个数N.(2 <= N <= 50000) 第2 - N + 1行,每行4个数,中间用空格分隔,分别表示矩形左下和右上端

【HDOJ6681】Rikka with Cake(扫描线,线段树)

题意:给定一个n*m的平面,有k条垂直或平行的直线,问将平面分成了几个互不联通的部分 n,m<=1e9,k<=1e5 思路: 刻在DNA里的二维数点 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned int uint; 5 typedef unsigned long long ull; 6 typedef pair<int,int> PI

poj 1151 线段树+扫描线

poj 1151 http://poj.org/problem?id=1151 大神orz 这是弱渣扫面线第一题,感觉区域赛有比较多的用的这个思想,所以赶在区域赛前熟悉一下扫描线和线段树(学习经验就是看着代码,然后一步一步测试,差不多就明白了 /************************************************************** Problem:poj 1151 User: youmi Language: C++ Result: Accepted Time