Bzoj4378--Poi2015Logistyka

主要被坑在了询问上(说的好像修改可以坑人一样

设已经超过s的数有k个。

如果k>=c那么显然可行

否则如果剩下的数的和>=(c-k)*s的话则有解,否则无解

简单证明一下 :

如果sum>=(c-k)*s,由于每个数都是小于s的,所以剩下数的个数>=(c-k)*s/(s-1)>(c-k),所以必然可以选出(c-k)个数。

选出一个数之和上式依然成立

如果sum<(c-k)*s,显然无解,根本不够取

代码 : (贴的

#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
#define N 1000005
using namespace std;  

int n,m,cnt,a[N],x[N],y[N],z[N],num[N],hash[N];
struct bit_node{
    ll c[N];
    void add(int x,int t){
        for (; x<=cnt; x+=x&-x) c[x]+=t;
    }
    ll qry(int x){
        ll t=0; for (; x; x-=x&-x) t+=c[x]; return t;
    }
}bit1,bit2;
int read(){
    int x=0; char ch=getchar();
    while (ch<‘0‘ || ch>‘9‘) ch=getchar();
    while (ch>=‘0‘ && ch<=‘9‘){ x=x*10+ch-‘0‘; ch=getchar(); }
    return x;
}
int find(int x){
    int l=1,r=cnt,mid;
    while (l<r){
        mid=(l+r)>>1;
        if (hash[mid]<x) l=mid+1; else r=mid;
    }
    return l;
}
int main(){
    n=read(); m=read(); int i,j; char ch;
    for (i=1; i<=m; i++){
        ch=getchar(); while (ch<‘A‘ || ch>‘Z‘) ch=getchar();
        x[i]=read(); y[i]=num[i]=read();
        z[i]=(ch==‘U‘)?1:0;
    }
    sort(num+1,num+m+1); hash[cnt=1]=num[1];
    for (i=2; i<=m; i++)
        if (num[i]!=num[i-1]) hash[++cnt]=num[i];
    for (i=1; i<=m; i++) y[i]=find(y[i]);
    for (i=1; i<=m; i++) if (z[i]){
        if (j=a[x[i]]){
            bit1.add(j,-1); bit2.add(j,-hash[j]);
        }
        a[x[i]]=y[i];
        bit1.add(y[i],1); bit2.add(y[i],hash[y[i]]);
    } else puts(bit2.qry(y[i]-1)>=(x[i]-bit1.qry(cnt)+bit1.qry(y[i]-1))*hash[y[i]]?"TAK":"NIE");
    return 0;
}
时间: 2024-10-26 17:47:40

Bzoj4378--Poi2015Logistyka的相关文章

【BZOJ4378】[POI2015]Logistyka 树状数组

[BZOJ4378][POI2015]Logistyka Description 维护一个长度为n的序列,一开始都是0,支持以下两种操作:1.U k a 将序列中第k个数修改为a.2.Z c s 在这个序列上,每次选出c个正数,并将它们都减去1,询问能否进行s次操作.每次询问独立,即每次询问不会对序列进行修改. Input 第一行包含两个正整数n,m(1<=n,m<=1000000),分别表示序列长度和操作次数.接下来m行为m个操作,其中1<=k,c<=n,0<=a<=

BZOJ4378 : [POI2015]Logistyka

对于每个询问,设不小于$s$的个数为$cnt$,小于$s$的和为$sum$. 那么如果可以进行$s$轮,当且仅当$sum\geq (c-cnt)\times s$. 权值线段树维护,时间复杂度$O(m\log m)$. 证明: 如果$cnt\geq c$,那么显然可以每次取$c$个. 否则如果$sum\geq (c-cnt)\times s$,那么小于$s$的个数必然不小于$c$,可以每次取最大的$c$个来完成. 当$sum<(c-cnt)\times s$时,那么无论怎么取,都是做不到$s$轮

【BZOJ4378】[POI2015]Logistyka【树状数组】【结论题】

[题目链接] 题解: 首先得有一个结论:设个数大于s的数字有k个(如果k大于c,显然是TAK.这里讨论k <= c),那么如果个数小于s的数字和不小于(c - k) * s,那么一定有解. 并不会证明... 用树状数组记录一下数字的个数以及数字的数字和,然后判断就可以了. 复杂度: 时间复杂度:O(mlogm),空间复杂度:O(m). 1A. GET: 结论题... /* Telekinetic Forest Guard */ #include <cstdio> #include <

poi2015 bzoj4377-4386训练

就按时间顺序写吧 完成度:8/10 3.30 bzoj4385 首先一定是删去连续d个数,然后枚举终点,起点显然有单调性,用单调队列乱搞搞就可以啦 bzoj4378 首先才结论:可行当且仅当把所有大于s的数全变成s然后看所有的数的和大于等于c*s,然后两个树状数组分别维护<=s的和及个数即可,注意需要离散化 3.31 bzoj4377 设一段的起点处的数为x,则m个限制条件就可以转化为x在若干个区间(或两个区间的并)里面,然后把这些区间交起来就得到了x的范围,算出个数然后减去最后m-1个数(没有

待 题表

题表 达哥终极杂题表Bzoj2839 hdu6021 Codeforces 804DBzoj2248 hdu5575 Codeforces 786CBzoj2013 bzoj2676 Codeforces 803CBzoj2386 bzoj3782 Codeforces 813DBzoj2699 cogs1667 Codeforces 814DBzoj4798 bzoj2064 Codeforces 814EBzoj4639 bzoj3505 Codeforces 815ABzoj4417 bz