BZOJ 1135 [POI2009]Lyz 线段树

题意:链接

方法:线段树维护子区间最值。

解析:

我们可以推出来一个式子。

就是如果满足题意的话。

那么任意一个子区间[l,r]

f[i]表示穿i的鞋的人数

(r?l+1+d)?k>=∑f[i](l<=i<=r)

d?k>=∑(f[i]?k)

所以维护个区间最大值即可。

最大值比d*k小的话显然满足。

复杂度O(nlogn+mlogn);

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 200100
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
typedef long long ll;
ll sum[N<<2],lmax[N<<2],rmax[N<<2],mmax[N<<2];
int n,m;
ll d;
ll k;
void pushup(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    lmax[rt]=max(lmax[rt<<1],sum[rt<<1]+lmax[rt<<1|1]);
    rmax[rt]=max(rmax[rt<<1|1],sum[rt<<1|1]+rmax[rt<<1]);
    mmax[rt]=max(lmax[rt<<1|1]+rmax[rt<<1],max(mmax[rt<<1],mmax[rt<<1|1]));
}
void build(int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]=lmax[rt]=rmax[rt]=mmax[rt]=-k;
        return;
    }
    int mid=(l+r)>>1;
    build(lson),build(rson);
    pushup(rt);
}
void update(int p,ll v,int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]+=v,lmax[rt]+=v,rmax[rt]+=v,mmax[rt]+=v;
        return;
    }
    int mid=(l+r)>>1;
    if(p<=mid)update(p,v,lson);
    else update(p,v,rson);
    pushup(rt);
}
ll getmax()
{
    return max(lmax[1],max(mmax[1],rmax[1]));
}
int main()
{
    scanf("%d%d%lld%lld",&n,&m,&k,&d);
    n-=d;
    build(1,n,1);
    for(int i=1;i<=m;i++)
    {
        ll ri,xi;
        scanf("%lld%lld",&ri,&xi);
        update(ri,xi,1,n,1);
        if(getmax()<=d*k)puts("TAK");
        else puts("NIE");
    }
} 

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-11-05 12:31:31

BZOJ 1135 [POI2009]Lyz 线段树的相关文章

BZOJ 1135 POI2009 Lyz 线段树+Hall定理

题目大意:有1~n型号的滑冰鞋,每种有k双,一个x号脚的人只能适应[x,x+d]号滑冰鞋,每次增加一些x号脚的人或减少一些x号脚的人,问能否匹配 http://m.blog.csdn.net/blog/u012732945/40707885 OTZ 这题我居然还能贡献一个WA真是醉了 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M

【BZOJ1135】[POI2009]Lyz 线段树

[BZOJ1135][POI2009]Lyz Description 初始时滑冰俱乐部有1到n号的溜冰鞋各k双.已知x号脚的人可以穿x到x+d的溜冰鞋. 有m次操作,每次包含两个数ri,xi代表来了xi个ri号脚的人.xi为负,则代表走了这么多人. 对于每次操作,输出溜冰鞋是否足够. Input n m k d ( 1≤n≤200,000 , 1≤m≤500,000 , 1≤k≤10^9 , 0≤d≤n ) ri xi ( 1≤i≤m, 1≤ri≤n-d , |xi|≤10^9 ) Output

bzoj 2120: 数颜色 线段树套平衡树

/************************************************************** Problem: 2120 User: wangyucheng Language: C++ Result: Time_Limit_Exceed ****************************************************************/ #include<iostream> #include<cstdio> #incl

Bzoj 2752 高速公路 (期望,线段树)

Bzoj 2752 高速公路 (期望,线段树) 题目链接 这道题显然求边,因为题目是一条链,所以直接采用把边编上号.看成序列即可 \(1\)与\(2\)号点的边连得是. 编号为\(1\)的点.查询的时候把\(r - 1\)就好了. 这里的期望显然就是路径的平均值. 期望值: \[\dfrac{\sum_{i=l}^r\sum_{j=l}^{r}dis[i][j]}{C_{r-l+1}^2}\] 下面部分可以直接算出: 上面这一部分比较难维护. 考虑每一条边会被走过多少次. \[ans = \su

BZOJ 3252 攻略 线段树

题意:链接 方法:线段树 解析: 闲的随机的题. 看完题后看着好像挺简单的. 既然每个点的权值只会传子树,并且整个图是严格的一棵树,所以应该是跟dfs序有关. 然后去看数据范围. 尼玛HINT是什么鬼. 既然这么说了那就想想怎么做吧=-= 并且因为价值都为正的,所以显然要考虑贪心,挑k条从叶节点到根的所有点权值和最大的k条. 并且每一挑完后都需要更新. 然后有一个性质,每个点至多选一次,也就是说每个点至多被删一次. 并且根节点到叶节点链上的所有点的路径上的点权和是随着深度递增的. 所以显然我们用

bzoj 2962 序列操作(线段树)

题外话 做这道题我整个人都非常的绝望,推了一会发现是线段树裸题,然后调了N久一直是WA 情况是这样的 开始WA的几百毫秒的都是由于我比较SB造成的,可是跑了10几秒的程序我查了N久也查不出错 最后灵机一动把50000改成60000就过了,也不知道为啥T_T Description 一个长度为n的序列,有3种操作 1:区间加c 2:区间取为相反数 3:询问区间中选择c个数相乘的所有方案的和mod19940417的值 Solution 这个操作3非常鬼畜,似乎没啥好的办法,但是仔细推导一番会发现这个

bzoj 1835 基站选址(线段树优化Dp)

Description 题意:有N个村庄坐落在一条直线上,第i(i>1)个村庄距离第1个村庄的距离为Di 需要在这些村庄中建立不超过K个通讯基站,在第i个村庄建立基站的费用为Ci 如果在距离第i个村庄不超过Si的范围内建立了一个通讯基站,那么就成它被覆盖了 如果第i个村庄没有被覆盖,则需要向他们补偿,费用为Wi 现在的问题是,选择基站的位置,使得总费用最小. Solution 首先可以想到dp,用dp[i][j]表示前i个村庄建了j个通讯站且第j个建在i处 dp[i][j]=min(dp[k][

bzoj 1858 序列操作(线段树)

题外话 本来想练练线段树的,然后发现这题及其蛋疼,要打一坨标记,这是我写过的最长的线段树了= = 然后我很SB的把R打成了r调了一个下午真是蛋疼QvQ Description: 给定一个0/1序列,有如下5个操作: 0:区间赋值为0 1:区间赋值为1 2:区间取反 3:询问区间内1的个数 4:询问区间内最大连续1的个数 Solution 没有操作4这显然就是个SB题,有了操作4我们需要打几个标记 我们需要从左端点开始连续0/1的个数,从右端点开始的连续0/1个数 区间内0/1个数,区间内最大连续

BZOJ 2124等差子序列 线段树&amp;&amp;hash

[题目描述 Description] 给一个 1 到 N 的排列{Ai},询问是否存在 1<=p1<p2<p3<p4<p5<…<pLen<=N(Len>=3),使得 Ap1,Ap2,Ap3,…ApLen 是一个等差序列. [输入描述 Input Description] 输入的第一行包含一个整数 T,表示组数. 下接 T 组数据,每组第一行一个整数 N,每组第二行为一个 1 到 N 的排列, 数字两两之间用空格隔开. [输出描述 Output Desc