HDU 4960 Handling the past 2014 多校9 线段树

首先确定的基本思想是按时间离散化后来建线段树,对于每个操作插入到相应的时间点上

但是难就难在那个pop操作,我之前对pop操作的处理是找到离他最近的那个点删掉,但是这样对于后面的peak操作,如果时间戳还在pop前面,那就需要还原之前的pop操作,这弄得很不方便

于是就有了一种类似扫描线的做法,对于push操作+1,pop操作-1,对于每次peak操作,从他这点往左走,找到第一个>0的点即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL __int64
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
using namespace std;
const int N = 50010;
int sum[N<<2],rsum[N<<2];
int d[N<<2];
int q[N],A[N],tmp[N],t[N];
int n;
void build(int rt,int l,int r)
{
    sum[rt]=rsum[rt]=0;
    if (l>=r){
       return;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
}
void up(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    rsum[rt]=max(rsum[rt<<1|1],sum[rt<<1|1]+rsum[rt<<1]);
}
void update(int val,int pos,int loc,int rt,int l,int r)
{
    if (l>=r){
        sum[rt]=val;
        rsum[rt]=val;
        if (val>0) d[rt]=A[loc];
        //if (val<0) rsum[rt]=0;
        return;
    }
    int mid=(l+r)>>1;
    if (pos<=mid)
    update(val,pos,loc,lson);
    else
    update(val,pos,loc,rson);
    up(rt);
}
int s;
int query(int pos,int rt,int l,int r)
{
    if (r<=pos){
        if (s+rsum[rt]<=0){
            s+=sum[rt];
            return -1;
        }
    }
    if (l>=r){
        return d[rt];
    }
    int mid=(l+r)>>1;
    if (pos<=mid) return query(pos,lson);
    int res=-1;
    res=query(pos,rson);
    if (res!=-1) return res;
    return query(pos,lson);

}
int main()
{
    char str[10];
    int kase=0;
    while (scanf("%d",&n)!=EOF)
    {
        if (n==0) break;
        for (int i=1;i<=n;i++){
            scanf("%s",str);
            if (str[1]==‘u‘){
                q[i]=1;
                scanf("%d%d",&A[i],&tmp[i]);
            }
            else
            if (str[1]==‘o‘){
                q[i]=2;
                scanf("%d",&tmp[i]);
            }
            else{
                q[i]=3;
                scanf("%d",&tmp[i]);
            }
            t[i]=tmp[i];
        }
        printf("Case #%d:\n",++kase);
        sort(t+1,t+1+n);
        for (int i=1;i<=n;i++){
            int pos=lower_bound(t+1,t+1+n,tmp[i])-t;
            tmp[i]=pos;
            //cout<<tmp[i]<<endl;
        }
        build(1,1,n);
        for (int i=1;i<=n;i++){
            if (q[i]==1){
                update(1,tmp[i],i,1,1,n);
            }
            else
            if (q[i]==2){
                update(-1,tmp[i],i,1,1,n);
            }
            else{
                if (tmp[i]<=1){
                 printf("-1\n");
                 continue;
                }
                s=0;
                int ans=query(tmp[i]-1,1,1,n);
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}

  

时间: 2024-08-04 00:06:05

HDU 4960 Handling the past 2014 多校9 线段树的相关文章

HDU_4893 2014多校三 线段树

给定一个初始都为0的序列,有三种操作,前两种比较正常,一个是对某个位置的数add k,另一个是query区间和.然后比较麻烦的是第三个操作,把某个区间里面的每个值改成离它最近的Fibonacci数,如果存在左右两个离它近的,优先取左边数值小的 一看到前两个操作马上就想上手敲树状数组,后来看到第三个就有点傻眼了,思维当时一直停留在怎么快速改值..但忽略了题目本身要求什么,只有操作2才是输出,也就是只要求区间和值而且,其他两个都是操作而已,在聪哥的提醒下,知道对线段树开两个值记录+一个懒惰标记,一个

hdu 4902 Nice boat(2014多校训练第4场 1006)

Nice boat                                                                           Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description There is an old country and the king fell in love with a d

hdu 4865 Peter&#39;s Hobby(2014 多校联合第一场 E)

题意:已知昨天天气与今天天气状况的概率关系(wePro),和今天天气状态和叶子湿度的概率关系(lePro)第一天为sunny 概率为 0.63,cloudy 概率 0.17,rainny 概率 0.2.给定n天的叶子湿度状态,求这n天最可能的天气情况 分析:概率dp设 dp[i][j] 表示第i天天气为j的最大概率,pre[i][j]表示第i天天气最可能为j的前一天天气,dp[i][j]=max(dp[i-1][k]+log(wePro[k][j])+log(lePro[j][lePos[i]]

HDU 4902 Nice boat 多校4 线段树

给定n个数 第一个操作和普通,区间覆盖性的,把l-r区间的所有值改成固定的val 第二个操作是重点,输入l r x 把l-r区间的所有大于x的数,变成gcd(a[i],x) a[i]即指满足条件的序列上的数值 最后才输出所有值 当时苦思这个地方如何优化,想着不可能单点去更新吧,但是区间gcd,不能保存下来,一来他是要>x才有效,本来聪哥想了一种先把各种x gcd一遍,最后在push下去,发现不行,就是因为他对>x才有效,你在区间就直接gcd了,那不是把不该gcd的也给搞了 还想过说先存起来所有

HDU 5023 A Corrupt Mayor&#39;s Performance Art (线段树)

A Corrupt Mayor's Performance Art Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 100000/100000 K (Java/Others) Total Submission(s): 255    Accepted Submission(s): 114 Problem Description Corrupt governors always find ways to get dirty money.

HDU 5023 A Corrupt Mayor&#39;s Performance Art(线段树+优美的位运算)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 Problem Description Corrupt governors always find ways to get dirty money. Paint something, then sell the worthless painting at a high price to someone who wants to bribe him/her on an auction, this

HDU 5023 A Corrupt Mayor&#39;s Performance Art(线段树区间更新)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色,有两种操作: P a b c  把区间a到b涂成c颜色 Q a b 查询区间a到b的颜色 线段树区间更新,每个节点保存的信息有,存储颜色的c,30种颜色可以压缩到一个int型里面存储,然后还有一个tot,表示这个区间一共有多少种颜色. 对于P操作,依次往下寻找,找要更新的区间,找到要更新的区间之前

hdu - 5023 - A Corrupt Mayor&#39;s Performance Art(线段树)

题意:一长由N小段组成的长条,每小段的初始颜色为2.现执行M个操作,每个操作是以下两种中的一种(0 < N <= 1,000,000; 0<M<=100,000) : P a b c --> 将段a到段b涂成颜色c,c是1, 2, ... 30中的一种(0 < a<=b <= N, 0 < c <= 30). Q a b --> 问段a到段b之间有哪几种颜色,按颜色大小从小到大输出(0 < a<=b <= N, 0 <

HDU 5068 Harry And Math Teacher( 矩阵乘法 + 线段树维护 )

HDU 5068 Harry And Math Teacher( 矩阵乘法 + 线段树维护 ) 题意: 首先是这题题意理解错误,,其次是这题无法理解状态... 已经不是英文有多烂的情况了,是中文没学好啊.....大学不学语文才是真正的硬伤啊 题目意思 有一个城堡有很多层楼, 每层楼有2个门,每个门里面又有两个楼梯,可以通往上一层的两个门 问,从x层楼到y层楼有多少中方法(不能返回) 具体看图吧,,,已经不会说话了 1 #include <cstdio> 2 #include <cstri