cf 1070C Cloud Computing(权值线段树+差分)

题意:https://codeforces.com/problemset/problem/1070/C

给你很多区间的物品,你可以在区间里花pi的钱最多买ci个,每天你必须有买k个的任务,问你这段区间走完你花的最少的钱。

思路:

看到区间就想到差分,如果给你一个数据结构可以很快的push一个东西,erase一个东西,并很快的知道买前k小的价钱,你不是就很容易做了吗

这个东西就是权值线段树,分分钟写好1A

#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#include <cstdio>//sprintf islower isupper
#include <cstdlib>//malloc  exit strcat itoa system("cls")
#include <iostream>//pair
#include <fstream>//freopen("C:\\Users\\13606\\Desktop\\Input.txt","r",stdin);
#include <bitset>
//#include <map>
//#include<unordered_map>
#include <vector>
#include <stack>
#include <set>
#include <string.h>//strstr substr strcat
#include <string>
#include <time.h>// srand(((unsigned)time(NULL))); Seed n=rand()%10 - 0~9;
#include <cmath>
#include <deque>
#include <queue>//priority_queue<int, vector<int>, greater<int> > q;//less
#include <vector>//emplace_back
//#include <math.h>
#include <cassert>
#include <iomanip>
//#include <windows.h>//reverse(a,a+len);// ~ ! ~ ! floor
#include <algorithm>//sort + unique : sz=unique(b+1,b+n+1)-(b+1);+nth_element(first, nth, last, compare)
using namespace std;//next_permutation(a+1,a+1+n);//prev_permutation
//******************
clock_t __START,__END;
double __TOTALTIME;
void _MS(){__START=clock();}
void _ME(){__END=clock();__TOTALTIME=(double)(__END-__START)/CLOCKS_PER_SEC;cout<<"Time: "<<__TOTALTIME<<" s"<<endl;}
//***********************
#define rint register int
#define fo(a,b,c) for(rint a=b;a<=c;++a)
#define fr(a,b,c) for(rint a=b;a>=c;--a)
#define mem(a,b) memset(a,b,sizeof(a))
#define pr printf
#define sc scanf
#define ls rt<<1
#define rs rt<<1|1
typedef pair<int,int> PII;
typedef vector<int> VI;
typedef unsigned long long ull;
typedef long long ll;
typedef double db;
const db E=2.718281828;
const db PI=acos(-1.0);
const ll INF=(1LL<<60);
const int inf=(1<<30);
const db ESP=1e-9;
const int mod=(int)1e9+7;
const int N=(int)1e6+10;

vector<vector<int> >in(N),out(N);
struct node
{
    int l,r,c,p;
}a[N];
struct Tnode
{
    ll ci,pi;
}tr[N<<2];
void Build(int l,int r,int rt)
{
    tr[rt].ci=tr[rt].pi=0;
    if(l==r)return;
    int mid=(l+r)>>1;
    Build(l,mid,rt<<1);
    Build(mid+1,r,rt<<1|1);
}
void update_dot(int pos,ll Ci,ll Pi,int l,int r,int rt)
{
    tr[rt].ci+=Ci;
    tr[rt].pi+=Ci*Pi;
    if(l==r)return;

    int mid=(l+r)>>1;
    if(pos<=mid)
        update_dot(pos,Ci,Pi,l,mid,rt<<1);
    else
        update_dot(pos,Ci,Pi,mid+1,r,rt<<1|1);
}
ll Query(ll sum,int l,int r,int rt)
{
    if(sum==0)return 0;
    if(l==r)
    {
        if(sum>tr[rt].ci)
            return tr[rt].ci*l;
        return sum*l;
    }
    int mid=(l+r)>>1;
    ll ans=0;

    if(sum<=tr[ls].ci)
        ans+=Query(sum,l,mid,ls);
    else
        ans+=Query(sum-tr[ls].ci,mid+1,r,rs)+tr[ls].pi;
    return ans;
}
void check(int pos,int l,int r,int rt){
    if(l==r)
    {
        pr("%lld %lld\n",tr[rt].ci,tr[rt].pi);
        return ;
    }
    int mid=(l+r)>>1;

    if(pos<=mid)
        check(pos,l,mid,rt<<1);
    else
        check(pos,mid+1,r,rt<<1|1);
}
void C(int tot,int n){
    fo(i,1,n)
        check(i,1,tot,1);
    pr("----------------------------------\n");
}

int main()
{
    int n,k,m;
    int top=0;
    sc("%d%d%d",&n,&k,&m);
    for(int i=1;i<=m;++i)
    {
        sc("%d%d%d%d",&a[i].l,&a[i].r,&a[i].c,&a[i].p);
        top=max(top,a[i].p);
        in[a[i].l].push_back(i);
        out[a[i].r+1].push_back(i);
    }
    ll ans=0;
    for(int i=1;i<=n;++i)
    {
        int sz=in[i].size();
        for(int j=0;j<sz;++j)
            update_dot(a[in[i][j]].p,a[in[i][j]].c,a[in[i][j]].p,1,top,1);
        sz=out[i].size();
        for(int j=0;j<sz;++j)
            update_dot(a[out[i][j]].p,-a[out[i][j]].c,a[out[i][j]].p,1,top,1);
        ans+=Query(k,1,top,1);
    //    C(top,n);
    }
    pr("%lld\n",ans);
    return 0;
}

/**************************************************************************************/

 

posted @ 2020-04-12 10:39  ZMWLxh  阅读(265)  评论(0编辑  收藏  举报