POI2011 MET-Meteors

首先看上来就可以进行二分,但是答案是n个,所以我们进行整体二分,每次分成两个集合,一个集合可以完成,一个不可以,然后继续二分即可。

学习了Vergil学长的做法,偷懒用了vector,然后luogu上90分,懒得用数组去模拟实现了(都是细节)——by VANE

#include<bits/stdc++.h>
using namespace std;
#define N 300005
long long c[N];
int n,m,k,goal[N],ans[N];
int L[N],R[N],A[N],vis_cnt;
int vis[N];
vector<int> S,g[N];
void clear(int x)
{
    if(vis[x]==vis_cnt) return;
    vis[x]=vis_cnt;
    c[x]=0;
}
inline int read()
{
    int x=0;char ch=getchar();int f=1;
    while(ch<'0'||ch>'9') {if(ch=='-') f=-f;ch=getchar();}
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void add(int x,int z)
{
    for(;x<=m;x+=x&-x)
    {
        clear(x);
        c[x]+=z;
    }
}
long long sum(int x)
{
    long long w=0;
    for(;x;x-=x&-x)
    {
        clear(x);
        w+=c[x];
    }
    return w;
}
void solve(int l,int r,vector<int> S)
{
    if(l==r)
    {
        int siz=S.size();
        for(int j=0;j<siz;++j) ans[S[j]]=l;
        return;
    }
    int mid=l+r>>1;
    vis_cnt++;
    for(int i=l;i<=mid;++i)
    {
        if(L[i]<=R[i])
        {
            add(L[i],A[i]);
            add(R[i]+1,-A[i]);
        }
        else
        {
            add(L[i],A[i]);
            add(1,A[i]);
            add(R[i]+1,-A[i]);
        }
    }
    int siz=S.size();
    vector<int> S1,S2;
    for(int j=0;j<siz;++j)
    {
        int u=S[j];
        int sizz=g[u].size();
        long long w=0;
        bool flag=0;
        for(int b=0;b<sizz;++b)
        {
            w+=sum(g[u][b]);
            if(w>=goal[u])
            {
                S1.push_back(u);
                flag=1;
                break;
            }
        }
        if(!flag)
        {
            S2.push_back(u);
            goal[u]-=w;
        }
    }
    if(S1.size()) solve(l,mid,S1);
    if(S2.size()) solve(mid+1,r,S2);
}
int main()
{
    n=read();m=read();
    for(int i=1;i<=m;++i) g[read()].push_back(i);
    for(int i=1;i<=n;++i) goal[i]=read();
    k=read();
    for(int i=1;i<=k;++i)
    {
        L[i]=read();
        R[i]=read();
        A[i]=read();
    }
    for(int i=1;i<=n;++i) S.push_back(i);
    solve(1,k+1,S);
    for(int i=1;i<=n;++i)
        if(ans[i]==k+1) puts("NIE");
        else printf("%d
",ans[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8059098.html