Solution [POI2011]MET-Meteors
题目大意:给定一个环,每个点有一个所属国家,多次事件,每次对一段区间上的每个点加上一个值,求每个国家最早多少次操作之后属于它的点的点权和能达到一个它的期望值
整体二分
分析
区间修改单点查询可以树状数组差分一下
不难想到暴力思路,对于每个国家,我们二分一个时间,暴力修改,然后单点查询
这样时间复杂度是(O(nklog_mlog_k)),应该是的?(n)个国家做(n)次操作,每次二分(log_k)次,每次树状数组复杂度(log_m),暴力做修改(k)次?
然后我们发现这玩意儿是可以用整体二分来优化的
首先我们假定当前答案区间在([l,r])内,我们每次做([l,mid])这段区间内的修改,如果一个国家已经达到期望就把它归到左队列,否则归到右队列,并且对其期望值做修改,只有这样才能保证时间复杂度(我就是每次改([1,mid]) (T)了一片发现自己写了个假算法……)
对于无解,我们加一个虚拟事件,把所有点点权加上无穷大
#include <cstdio>
#include <cctype>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 100;
inline int read(){
int x = 0;char c = getchar();
while(!isdigit(c))c = getchar();
while(isdigit(c))x = x * 10 + c - '0',c = getchar();
return x;
}
int mxwant;
namespace BIT{
ll f[maxn];
int t[maxn],tim;
inline int lowbit(int x){return x & (-x);}
inline void clear(){tim++;}
inline void add(int pos,int val){
while(pos < maxn){
if(t[pos] < tim)t[pos] = tim,f[pos] = 0;
f[pos] += val;
pos += lowbit(pos);
}
}
inline ll query(int pos){
ll res = 0;
while(pos){
if(t[pos] < tim)t[pos] = tim,f[pos] = 0;
res += f[pos];
pos -= lowbit(pos);
}
return res;
}
}
struct Event{
int l,r,val;
}event[maxn];
vector<int> vec[maxn];
int n,m,k,id[maxn],want[maxn],q[maxn],q1[maxn],q2[maxn],ans[maxn];
inline void modify(int l,int r,int val){
if(l <= r)BIT::add(l,val),BIT::add(r + 1,-val);
else BIT::add(l,val),BIT::add(1,val),BIT::add(r + 1,-val);
}
inline void solve(int l,int r,int ql,int qr){
if(ql > qr)return;
if(l == r){
for(int i = ql;i <= qr;i++)ans[q[i]] = l;
return;
}
int mid = (l + r) >> 1,pos1 = 0,pos2 = 0,pos = ql;
for(int i = l;i <= mid;i++)
modify(event[i].l,event[i].r,event[i].val);
for(int i = ql;i <= qr;i++){
ll tmp = 0;
for(int x : vec[q[i]]){
tmp += BIT::query(x);
if(tmp > want[q[i]])break;
}
if(tmp >= want[q[i]])q1[++pos1] = q[i];
else want[q[i]] -= tmp,q2[++pos2] = q[i];
}
BIT::clear();
for(int i = 1;i <= pos1;i++)q[pos++] = q1[i];
for(int i = 1;i <= pos2;i++)q[pos++] = q2[i];
solve(l,mid,ql,ql + pos1 - 1),solve(mid + 1,r,ql + pos1,qr);
}
int main(){
n = read(),m = read();
for(int i = 1;i <= m;i++)vec[read()].push_back(i);
for(int i = 1;i <= n;i++)want[i] = read(),mxwant = max(mxwant,want[i]);
k = read();
for(int i = 1;i <= k;i++)
event[i].l = read(),event[i].r = read(),event[i].val = read();
event[k + 1].l = 1,event[k + 1].r = m,event[k + 1].val = 0x7fffffff;
for(int i = 1;i <= n;i++)q[i] = i;
solve(1,k + 1,1,n);
for(int i = 1;i <= n;i++)
if(ans[i] == k + 1)printf("NIE
");
else printf("%d
",ans[i]);
return 0;
}