[POI2011]MET-Meteors

Solution

如果只考虑一个国家就很好做,直接二分答案,用树状数组维护过程即可。单次 \(O(n\log k)\)\(m\) 次就是 \(O(nm\log k)\)

但是发现每次二分树状数组的操作一模一样,所以考虑整体二分,这样就可以了。

#include<stdio.h>
#include<vector>
#define int __int128
using namespace std;

inline int read(){
    int x=0,flag=1; char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')flag=0;c=getchar();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
    return flag? x:-x;
}

void print(int x){
    if(x>9) print(x/10);
    putchar(x%10+'0');
}

const int N=3e5+7;

struct Seg{
    int l,r,v;
}q[N];

vector<int> pos[N];
int m,n,P[N],a[N],c[N],ans[N];
inline int lowbit(int x){return -x&x;}
inline void add(int x,int v){while(x<=n)c[x]+=v,x+=lowbit(x);}
inline int query(int x){int ret=0;while(x)ret+=c[x],x-=lowbit(x);return ret;}

void Add(int l,int r,int x){
    if(l<=r) add(l,x),add(r+1,-x);
    else add(l,x),add(n+1,-x),add(1,x),add(r+1,-x);
}

void solve(const vector<int> &V,int l,int r){
    if(!V.size()) return ;
    int mid=(l+r)>>1;
    for(int i=l;i<=mid;i++) Add(q[i].l,q[i].r,q[i].v);
    vector<int> L,R;
    for(int i=0;i<V.size();i++){
    	int ret=0,x=V[i];
    	for(int j=0;j<pos[x].size();j++)
            ret+=query(pos[x][j]);
      	if(ret>=P[x]) ans[x]=mid,L.push_back(x);
    	else R.push_back(x);
    }
    if(l!=r) solve(R,mid+1,r);
    for(int i=l;i<=mid;i++) Add(q[i].l,q[i].r,-q[i].v);
    if(l!=r) solve(L,l,mid);
}

signed main(){
    vector<int> V;
    m=read(),n=read();
    for(int i=1;i<=n;i++) pos[read()].push_back(i);
    for(int i=1;i<=m;i++) P[i]=read(),V.push_back(i);
    int k=read();
    for(int i=1;i<=k;i++)
        q[i].l=read(),q[i].r=read(),q[i].v=read();
    solve(V,1,k);
    for(int i=1;i<=m;i++)
    if(ans[i]) print(ans[i]),putchar('\n');
    else printf("NIE\n");
}
posted @ 2021-07-16 14:04  Kreap  阅读(29)  评论(0编辑  收藏  举报