P3586 [POI2015] LOG 题解
维护一个长度为
- 将序列中第
个数修改为 。 - 在这个序列上,每次选出
个正数,并将它们都减去 ,询问能否进行 次操作。
对于
题意比较抽象,解题关键在于理解。
以下对一种可能的序列
- 如何理解能否进行s次操作。
设存在
-
对于
, 次选择都使用,即最多被使用 次。因为 ,所以只需关注 。 -
对于
,可以凑一凑,让每个都能被利用上,即凑出 个。(证明请看洛谷题解)。
两种方式共有
- 时间复杂度?
求
可以维护一个升序序列,再用前缀和,使用树状数组优化前缀和。
得单点修改序列
具体细节见代码。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e6+1;
int n,a[N],m,q[N],l1[N],l2[N],cnt,len;
char s[N];
struct tree{
int c[N];
int lowbit(int x) {
return x & -x;
}
void upd(int x,int k) {//将第 x 加 k
for(int i=x;i<=len;i+=lowbit(i)) {
c[i]+=k;
}
}
int s(int x) {
int p=0;
for(int i=x;i;i-=lowbit(i)) {
p+=c[i];
}
return p;
}
}t1,t2;
//t1 维护a次数 ;t2 维护a和
signed main() {
cin>>n>>m;
for(int i=1;i<=m;i++) {
cin>>s[i]>>l1[i]>>l2[i];
if(s[i]=='U')
a[++cnt]=l2[i];
}
sort(a+1,a+cnt+1);
len=unique(a+1,a+cnt+1)-(a+1);//此处去重,方便统计出现次数
for(int i=1;i<=m;i++) {
int wh=lower_bound(a+1,a+len+1,l2[i])-a;
if(s[i]=='U') {
int y=l1[i];
if(q[y]) {
// cout<<i<<"114514";
int wh2=lower_bound(a+1,a+len+1,q[y])-a;
t1.upd(wh2,-1);
t2.upd(wh2,-q[y]);
}
t1.upd(wh,1);
t2.upd(wh,l2[i]);
q[l1[i]]=l2[i];
}
if(s[i]=='Z') {
int bigger=t1.s(len)-t1.s(wh-1);
int smaller=t2.s(wh-1);
printf("%s\n",(bigger+smaller/l2[i]>=l1[i]?"TAK":"NIE"));
}
}
return 0;
}
本文作者:cjrqwq
本文链接:https://www.cnblogs.com/yfzqwq/p/18492828
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步