HDU 4325-Flowers(线段树+离散化)

题意:

给出每个花开花的时间段,每询问一个时间点输出该时间点开花的数量

分析:

线段树的区间更新,单点查询,但发现时间很大,没法存区间,就想到了离散化。

离散化就是把要处理的数据统一起来重新标号。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson l,m,rt<<1
#define pi acos(-1.0)
#define rson m+1,r,rt<<1|1
#define All 1,N,1
#define N 100010
#define read freopen("in.txt", "r", stdin)
const ll  INFll = 0x3f3f3f3f3f3f3f3fLL;
const int INF= 0x7ffffff;
const int mod =  1000000007;
int res[N*8],q[N],sl[N],er[N];
ll sum[N*8],add[N*8],total;
void pushup(int rt){
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void pushdown(int rt,int len){
    if(add[rt]){
        add[rt<<1]+=add[rt];
        add[rt<<1|1]+=add[rt];
        sum[rt<<1]+=1LL*(len-len/2)*add[rt];
        sum[rt<<1|1]+=1LL*(len/2)*add[rt];
        add[rt]=0;
    }
}
void build(int l,int r,int rt){
    sum[rt]=add[rt]=0;
    if(l==r)return;
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    //pushup(rt);
}
void update(int L,int R,int v,int l,int r,int rt){
    if(L<=l&&R>=r){
        add[rt]+=v;
        sum[rt]+=(r-l+1)*v;
        return;
    }
    pushdown(rt,r-l+1);
    int m=(l+r)>>1;
    if(L<=m)update(L,R,v,lson);
    if(R>m)update(L,R,v,rson);
    pushup(rt);
}
ll query(int v,int l,int r,int rt){
        if(l==r){
            return sum[rt];
        }
    pushdown(rt,r-l+1);
    int m=(l+r)>>1;
    if(v<=m)return query(v,lson);
    else return query(v,rson);
}
int main()
{
    int t,n,m,test=0;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        int len=0;
        for(int i=0;i<n;++i){
            scanf("%d%d",&sl[i],&er[i]);
            res[++len]=sl[i];
            res[++len]=er[i];
        }
        for(int i=0;i<m;++i){
            scanf("%d",&q[i]);
            res[++len]=q[i];
        }
        sort(res+1,res+len+1);
        int tmp=unique(res+1,res+len+1)-(res+1);
        for(int i=tmp;i>=2;i--)
        {
            if(res[i]!=res[i-1]+1)res[++tmp]=res[i-1]+1;
        }
        sort(res+1,res+tmp+1);
        build(1,tmp,1);
        for(int i=0;i<n;++i){
            int ll=lower_bound(res+1,res+tmp+1,sl[i])-res;
            int rr=lower_bound(res+1,res+tmp+1,er[i])-res;
            update(ll,rr,1,1,tmp,1);
        }
        printf("Case #%d:\n",++test);
       for(int i=0;i<m;++i){
            int p=lower_bound(res+1,res+tmp+1,q[i])-res;
            printf("%I64d\n",query(p,1,tmp,1));
        }
    }
return 0;
}
时间: 2024-07-31 10:45:06

HDU 4325-Flowers(线段树+离散化)的相关文章

hdoj 4325 Flowers 线段树+离散化

hdoj 4325 Flowers 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4325 思路: 直接线段树,按照花的开放区间的大小建树,要注意虽然花的周期数据可能会达到1e9,这样的话线段树开四倍时不可能的.但是我们可以看到一共可能的数据时N行,那么每行两个数,再开4倍的区间.计算下来,在离散化的帮助下,我们只需要开8*N被的线段树即可. 另外询问的数据也需要放入离散化的范围,如果不这样做,有可能在询问时使用lower_bound函数会导致数

HDU 1542 Atlantis 线段树+离散化+扫描线

题意:给出一些矩形的最上角坐标和右下角坐标,求这些矩形的面积并. NotOnlySuccess 线段树专辑中扫描线模板题,弱智的我对着大大的代码看了一下午才搞懂. 具体见思路见注释=.= #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define lson rt<<1,l,mid #define rson rt<<1|1,mid

POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算

求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的,这样理论上是对的 要注意处理高度相同的线段,把底边优先处理(在代码里就是f标记为1的线段),因为若是一个矩形的底边和另一个矩形的上边重合,则这个轮廓肯定不能算 不过POJ和HDU的数据好像都比较弱,我没进行上面的细节处理也AC了,不过一个很简单的数据就会不对,所以还是要处理一下才是真正正确的代码 我

hdu 4325 Flowers(区间离散化)

http://acm.hdu.edu.cn/showproblem.php?pid=4325 Flowers Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2633    Accepted Submission(s): 1290 Problem Description As is known to all, the blooming t

HDU 1542 Atlantics 线段树+离散化扫描

将 x 轴上的点进行离散化,扫描线沿着 y 轴向上扫描 每次添加一条边不断找到当前状态有效边的长度 , 根据这个长度和下一条边形成的高度差得到一块合法的矩形的面积 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 6 using namespace std; 7 8 const int MAX=200+10; 9 int flag[MAX&l

HDU 4325 Flowers(树状数组)

Flowers Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 3150    Accepted Submission(s): 1549 Problem Description As is known to all, the blooming time and duration varies between different kinds

HDU 3743 Frosh Week (线段树+离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3743 Frosh Week Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 5   Accepted Submission(s) : 1 Font: Times New Roman | Verdana | Georgia Font Size: 

HDU 3642 线段树+离散化+扫描线

题意:给你N个长方体的左下角和右上角坐标,问你空间中有多少体积是被大于两个不同的立方体覆盖的.x,y~10^6 z~500 考虑到给的z比较小,所以可以直接枚举z,然后跑二维的扫描线就好. 关于处理被不同的线段覆盖三次的问题,可以维护四个信息,cnt,once,twice,more,然后相互推出结果就好. #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #

HDU 1255 覆盖的面积 (扫描线 线段树 离散化)

题目链接 题意:中文题意. 分析:纯手敲,与上一道题目很相似,但是刚开始我以为只是把cnt>=0改成cnt>=2就行了,. 但是后来发现当当前加入的线段的范围之前 还有线段的时候就不行了,因为虽然现在都不等于 2,但是之前的那个线段加上现在的已经覆盖2次了. 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <cstring> 5 #include &