문제 밸리 P4602 [[CTSC2018] 혼합 과일 주스] 로스 솔루션

쿼리가 절반 대답에 의해 해결 될 수 있도록이 문제의 모노톤 지적했다.

폴리 질문의 경우, 전체의 절반의 사용은 처리에.

보도 주스 \ (D \) 하기 위해, 두 위치의 분리 내림차순으로 정렬 \ (MID를 \) 위치 만 고려, \ (MID \) 상기 위치 전에 주스, \ (MID \) 과일 주스 \ (D를 \) 모든 참여 맛 주스 혼합 정도의 최소값은 두 분리 된 것이다.

결정적인에서 \ (MID를 \) 모든 주스를 구입하는 가격입니다 볼륨 및 가격과 각각의 접두사에 의해 공정 그것을 밖으로 주스, 전에 접두사의 법적, 모든 볼륨이없는 경우.

그런 다음 질문에 대해, 당신이 판단 할 수있는, 그 볼륨의 요구를 충족하기 위해 최소 가격을 찾기 위해 반을 실시합니다 \ (중간 \) 불법 여부를.

프리픽스와 같은 동작을 위해, 펜윅 트리에 의해 달성 될 수있다 \ (MID는 \) 조정 변경한다.

특정 구현 세부 사항은 코드를 볼 수 있습니다.

\(암호\)

#include<bits/stdc++.h>
#define maxn 200010
#define inf 1000000000000000000
#define lowbit(x) (x&(-x))
using namespace std;
typedef long long ll;
template<typename T> inline void read(T &x)
{
    x=0;char c=getchar();bool flag=false;
    while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    if(flag)x=-x;
}
ll n,m,now,ma;
ll ans[maxn];
struct node
{
    ll d,p,l;
}t[maxn];
bool cmp(const node &a,const node &b)
{
    return a.d>b.d;
}
struct query
{
    ll g,l;
    int id;
}q[maxn],q1[maxn],q2[maxn];
struct Tree
{
    ll tr[maxn];
    void update(int x,ll v)
    {
        while(x<=ma)
            tr[x]+=v,x+=lowbit(x);
    }
    ll query(int x)
    {
        ll sum=0;
        while(x)
            sum+=tr[x],x-=lowbit(x);
        return sum;
    }
}Li,Pr;
void change(int x,int type)
{
    Li.update(t[x].p,type*t[x].l),Pr.update(t[x].p,type*t[x].p*t[x].l);
}
ll find(int x)
{
    int l=1,r=ma,pr=ma;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(Li.query(mid)>=q[x].l) pr=mid,r=mid-1;
        else l=mid+1;
    }
    return pr;
}
void solve(int L,int R,int l,int r)
{
    if(L>R) return;
    if(l==r)
    {
        for(int i=L;i<=R;++i) ans[q[i].id]=t[l].d;
        return;
    }
    int mid=(l+r)>>1;
    while(now<mid) change(++now,1);
    while(now>mid) change(now--,-1);
    int cnt1=0,cnt2=0;
    for(int i=L;i<=R;++i)
    {
        ll pr=find(i),lv=Li.query(pr),pv=Pr.query(pr);
        if(lv>=q[i].l&&pv-pr*(lv-q[i].l)<=q[i].g) q1[++cnt1]=q[i];
        else q2[++cnt2]=q[i];
    }
    for(int i=1;i<=cnt1;++i) q[L+i-1]=q1[i];
    for(int i=1;i<=cnt2;++i) q[L+cnt1+i-1]=q2[i];
    solve(L,L+cnt1-1,l,mid),solve(L+cnt1,R,mid+1,r);
}
int main()
{
    read(n),read(m);
    for(int i=1;i<=n;++i)
        read(t[i].d),read(t[i].p),read(t[i].l),ma=max(ma,t[i].p);
    t[++n].d=-1,t[n].p=1,t[n].l=inf,sort(t+1,t+n+1,cmp);
    for(int i=1;i<=m;++i) read(q[i].g),read(q[i].l),q[i].id=i;
    solve(1,m,1,n);
    for(int i=1;i<=m;++i) printf("%lld\n",ans[i]);
    return 0;
}

추천

출처www.cnblogs.com/lhm-/p/12630109.html