码迷,mamicode.com
首页 > 其他好文 > 详细

Serge and Dining Room(线段树)

时间:2019-07-07 09:50:02      阅读:182      评论:0      收藏:0      [点我收藏+]

标签:维护   none   png   pen   输出   math   play   坐标   下标   

E - Serge and Dining Room(线段树)

 CodeForces - 1180E

题意:给出a 和 b 数组,a为各种食物的价格,b为一列排着队的小朋友拥有的钱,小朋友排队购买食物,每个人都买自己能买的起的最贵的食物,买不起就离开队伍。给出q次操作,操作1是修改食物的价格,操作2是修改小朋友的钱,每次操作后询问当小朋友买完之后,能买到的最贵的食物的价格是多少,没有食物了就输出-1.

题解:直接拿kk的题解写法:

首先,小朋友的顺序对最终答案没有任何影响,因为如果两个小朋友能买两个东西,这两个小朋友无论怎么换,都是能买的了的。

  其次,对于一个价格为x的物品,如果有一个钱大于等于x的小朋友,就可以买走这个物品。如果我们把价格想象成一条数轴,那么物品就是1,小朋友就是-1,价格或者钱就是坐标轴的位置,这道题就转化成了求最大的后缀和大于等于1的下标。

  最后,我们用线段树来维护这个值,注意用线段树维护最大后缀和时,在查询时要注意后面的区间的影响。

(cin cout清空缓存貌似对于codeforce的多组输出会有影响,去掉了cin,cout的加速就过了,不然一直wa3)

 技术图片

技术图片

 

技术图片
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
#include<string.h>
using namespace std;
#define ll long long

const int maxn = 1e6 + 10;
const int INF = 0x3f3f3f3f;

int n,m;
int a[maxn],b[maxn];
int sum[maxn << 2],maxx[maxn << 2];

void update(int o,int l,int r,int ind,int ans)
{
    if(l == r)
    {
        sum[o] += ans;
        maxx[o] += ans;
        return ;
    }
    int mid = (l + r) >> 1;
    if(ind <= mid)
        update(o << 1,l,mid,ind,ans);
    else
        update(o << 1 | 1,mid + 1,r,ind,ans);
    sum[o] = sum[o << 1] + sum[o << 1 | 1];
    maxx[o] = max(maxx[o << 1 | 1],maxx[o << 1] + sum[o << 1 | 1]);
}

struct node
{
    int max,sum;
};
int query(int o,int l,int r,node temp)
{
    if(l == r)
        return l;
    int mid = (l + r) >> 1;
    node t;
    t.sum = temp.sum + sum[o << 1 | 1];
    t.max = temp.sum + maxx[o << 1 | 1];
    if(t.max > 0)
        return query(o << 1 | 1,mid + 1,r,temp);
    else
        return query(o << 1,l,mid,t);
}
int main()
{
    //ios::sync_with_stdio(false); cin.tie(0);cout.tie(0);
    memset(sum,0,sizeof(sum));
    memset(maxx,0,sizeof(maxx));
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
    {
        cin >> a[i];
        update(1,1,maxn-1,a[i],1);
    }
    for(int i = 1; i <= m; i++)
    {
        cin >> b[i];
        update(1,1,maxn-1,b[i],-1);
    }
    int q;

    cin >> q;
    while(q--)
    {
        int op,pos,val;
        cin >> op >> pos >> val;
        if(op == 1)         //
        {
            update(1,1,maxn-1,a[pos],-1);

            update(1,1,maxn-1,a[pos] = val,1);
        }
        else
        {
            update(1,1,maxn-1,b[pos],1);

            update(1,1,maxn-1,b[pos] = val,-1);
        }
        if(maxx[1] <= 0)
            puts("-1");
        else
            cout << query(1,1,maxn-1,{0,0})<<endl;
    }
}
View Code

 

Serge and Dining Room(线段树)

标签:维护   none   png   pen   输出   math   play   坐标   下标   

原文地址:https://www.cnblogs.com/smallhester/p/11144900.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!