[POI2015]Logistyka
[POI2015]Logistyka
题目大意:
一个长度为\(n(n\le10^6)\)的数列\(A_i\),初始全为\(0\)。操作共\(m(m\le10^6)\)次,包含以下两种:
- 将\(A_x\)修改为\(y\);
- 询问若每次任意选择\(x\)个正数,将它们\(-1\),能否操作\(y\)次。
思路:
用\(cnt\)表示不小于\(y\)的数的个数,\(sum\)表示小于\(y\)的数之和。
一个结论是,当\(sum\ge(x-cnt)\times y\)时可行,否则不可行。
证明参考Claris博客。
时间复杂度\(\mathcal O(m\log n)\)。
源代码:
#include<cstdio>
#include<cctype>
#include<algorithm>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
inline char getalpha() {
register char ch;
while(!isalpha(ch=getchar()));
return ch;
}
const int N=1e6+1,M=1e6;
typedef long long int64;
struct Query {
bool opt;
int x,y;
};
Query q[M];
int tmp[N],w[N];
class SegmentTree {
#define _left <<1
#define _right <<1|1
#define mid ((b+e)>>1)
private:
int64 val[2][N<<2],*cnt,*sum;
void push_up(const int &p) {
cnt[p]=cnt[p _left]+cnt[p _right];
sum[p]=sum[p _left]+sum[p _right];
}
public:
SegmentTree() {
cnt=val[0];
sum=val[1];
}
void modify(const int &p,const int &b,const int &e,const int &x,const int &y) {
if(b==e) {
cnt[p]+=y;
sum[p]+=tmp[x]*y;
return;
}
if(x<=mid) modify(p _left,b,mid,x,y);
if(x>mid) modify(p _right,mid+1,e,x,y);
push_up(p);
}
int64 query(const int &p,const int &b,const int &e,const int &l,const int &r,const bool &t) const {
if(b==l&&e==r) return val[t][p];
int64 ret=0;
if(l<=mid) ret+=query(p _left,b,mid,l,std::min(mid,r),t);
if(r>mid) ret+=query(p _right,mid+1,e,std::max(mid+1,l),r,t);
return ret;
}
#undef _left
#undef _right
#undef mid
};
SegmentTree t;
int main() {
const int n=getint(),m=getint();
for(register int i=0;i<m;i++) {
const char opt=getalpha();
const int x=getint(),y=getint();
q[i]=(Query){opt=='Z',x,y};
tmp[++tmp[0]]=y;
}
std::sort(&tmp[1],&tmp[tmp[0]]+1);
tmp[0]=std::unique(&tmp[1],&tmp[tmp[0]]+1)-&tmp[1];
for(register int i=0;i<m;i++) {
q[i].y=std::lower_bound(&tmp[1],&tmp[tmp[0]]+1,q[i].y)-tmp;
const int &x=q[i].x,&y=q[i].y;
if(q[i].opt) {
const int cnt=t.query(1,1,tmp[0],y,tmp[0],0);
const int64 sum=y!=1?t.query(1,1,tmp[0],1,y-1,1):0;
puts(sum>=(int64)(x-cnt)*tmp[y]?"TAK":"NIE");
} else {
if(w[x]) t.modify(1,1,tmp[0],w[x],-1);
w[x]=y;
if(w[x]) t.modify(1,1,tmp[0],w[x],1);
}
}
return 0;
}