3 条题解

  • 0
    @ 2023-9-7 18:35:23

    暑假的救赎day5 有一个事情是贪心没太讲出来啊 浅说一下,对于任意数量k的牛,你可以拆成k组数量为1的牛,所以你根本不用去思考数量问题 所以问题退化成了有多少个区间可以堆在这个要求的区间内,用线段树去统计当前这段处理区间内还可以填几个,把能填的填进来 贪心策略是以右端点排序,本质上是贪心。证明看课程视频!

    #include <bits/stdc++.h>
    using namespace std;
    
    int n,k,c;
    struct Node{
    	int sign = 0,mx = 0;
    };
    struct Qu{
    	int l,r,de;
    };
    Qu a1[50005];
    Node a[200005];
    bool cmp(Qu x,Qu y)
    {
    	if(x.r == y.r)
    	{
    		return x.l < y.l;
    	}
    	return x.r < y.r;
    }
    void push_down(int k)
    {
    	a[k*2].sign += a[k].sign;
    	a[k*2+1].sign += a[k].sign;
    	a[k*2].mx += a[k].sign;
    	a[k*2+1].mx += a[k].sign;
    	a[k].sign = 0;
    }
    void push_up(int k)
    {
    	a[k].mx = max(a[k*2].mx,a[k*2+1].mx); 
    }
    void add(int k,int l,int r,int s,int t,int sp)
    {
    	if(s <= l && r <= t)
    	{
    		a[k].sign += sp;
    		a[k].mx += sp;
    		return;
    	}
    	if(a[k].sign)
    	    push_down(k);
    	int mid = (l + r) /2;
    	if(s <= mid) add(k*2,l,mid,s,t,sp);
    	if(t > mid) add(k*2+1,mid+1,r,s,t,sp);
    	push_up(k);
    }
    int find(int k,int l,int r,int s,int t)
    {
    	if(s <= l && r <= t)
    	{
    		return a[k].mx;
    	}
    	if(a[k].sign)
    	    push_down(k);
    	int maxn = -1;
    	int mid = (l + r)/2;
    	if(s <= mid) maxn = max(maxn , find(k*2,l,mid,s,t));
    	if(t > mid) maxn = max(maxn, find(k*2+1,mid+1,r,s,t));
    	return maxn;
    }
    int main()
    {
    	cin >> k >> n >> c;
    	for(int i=1; i <= k ;i++)
    	{
    		cin >> a1[i].l >> a1[i].r >> a1[i].de;
    	}
    	sort(a1+1,a1+k+1,cmp);
    	int ans = 0;
    	for(int i=1; i <= k ;i++)
    	{
    		int b = find(1,1,n,a1[i].l,a1[i].r-1);
    		add(1,1,n,a1[i].l,a1[i].r-1,min(c-b,a1[i].de));
    		ans += min(c-b,a1[i].de);
    	}
    	cout << ans;
    }
    
    • 0
      @ 2023-6-15 16:37:17

      image image

      #include <bits/stdc++.h>
      #define ll long long
      #define mid (l+r>>1)
      using namespace std;
      const int N=20005;
      int n,m,k,s,t,c,ans;
      struct node1{
      	int l,r,k;
      	bool operator<(const node1 &k)const{
      		return r<k.r;
      	}
      }a[N*3];
      struct node{
      	int mx[N<<2],sign[N<<2];
      	void down(int p){
      		if (!sign[p]) return;
      		sign[p<<1]+=sign[p];mx[p<<1]+=sign[p];
      		sign[p<<1|1]+=sign[p];mx[p<<1|1]+=sign[p];
      		sign[p]=0;
      	}
      	void update(int p){
      		mx[p]=max(mx[p<<1],mx[p<<1|1]);
      	}
      	void add(int p,int l,int r,int s,int t,int k){
      	// 区间[s,t] +k
      		if (l>=s && r<=t){
      			sign[p]+=k;
      			mx[p]+=k; 
      			return;
      		} 
      		down(p);
      		if (s<=mid) add(p<<1,l,mid,s,t,k);
      		if (t>mid) add(p<<1|1,mid+1,r,s,t,k);
      		update(p);
      	}
      	int query(int p,int l,int r,int s,int t){
      	//查询区间最大值 
      		if (l>=s && r<=t) return mx[p];
      		down(p);
      		int xx=0;
      		if (s<=mid) xx=query(p<<1,l,mid,s,t);
      		if (t>mid) xx=max(xx,query(p<<1|1,mid+1,r,s,t));
      		return xx;	
      	}
      }T;
      int main(){
      	cin>>k>>n>>c;
      	for (int i=1;i<=k;++i){
      		cin>>a[i].l>>a[i].r>>a[i].k;
      		a[i].r-=1;
      	}
      	//按区间右端点排序 
      	sort(a+1,a+1+k);
      	for (int i=1;i<=k;++i){
      		//计算出区间最大值 
      		int maxn=T.query(1,1,n,a[i].l,a[i].r);  
      		//能选择的奶牛数量=min(c-maxn,该组奶牛的数量) 
      		int p=min(c-maxn,a[i].k);
      		ans+=p;//累加答案 
      		T.add(1,1,n,a[i].l,a[i].r,p);//区间增加p 
      	}
      	cout<<ans;
      }
      
      • 0
        @ 2023-6-10 17:23:15
        #include<iostream>
        #include<cstdio>
        #include<cstring>
        #include<algorithm>
        using namespace std;
        const int MAXN=5e4+10;
        int n,k,ans,c;
        struct Line{
        	int m,l,r;
        	bool operator<(const Line& l2)const{
        		return r < l2.r;
        	}
        }line[MAXN];
        int zt[MAXN];
        int tree[MAXN<<2],tag[MAXN<<2];
        inline int lc(int x){return x<<1;}
        inline int rc(int x){return lc(x)|1;}
        void push_up(int);
        void push_down(int);
        int query(int,int,int,int,int);
        void update(int,int,int,int,int,int);
        int main(){
        	scanf("%d%d%d",&k,&n,&c);
        	for(int i=1;i<=k;i++){
        		scanf("%d%d%d",&line[i].l,&line[i].r,&line[i].m);
        	}
        	sort(line+1,line+1+k);
        	for(int i=1;i<=k;i++){
        		int l = line[i].l,r = line[i].r,m = line[i].m;
        		//max [l,r)
        		int maxn = query(1,1,n,l,r-1);
        		int chose =((c-maxn) < m)?(c-maxn):m;
        		ans += chose;
        		//[l,r) += chose
        		update(1,1,n,l,r-1,chose);
        	}
        	cout<<ans;
        	return 0;
        }
        void push_up(int x){
        	tree[x] = max(tree[lc(x)],tree[rc(x)]);
        }
        void push_down(int x){
        	tree[lc(x)] += tag[x];
        	tree[rc(x)] += tag[x];
        	tag[lc(x)] += tag[x];
        	tag[rc(x)] += tag[x]; 
        	tag[x] = 0; 
        }
        int query(int x,int l,int r,int ql,int qr){
        	if(ql <= l && qr >= r){
        		return tree[x];
        	}
        	int mid = (l+r)>>1;
        	int ans = 0;
        	push_down(x);
        	if(ql <= mid){
        		ans = max(ans,query(lc(x),l,mid,ql,qr));
        	}
        	if(qr > mid){
        		ans = max(ans,query(rc(x),mid+1,r,ql,qr));
        	}
        	push_up(x);
        	return ans;
        }
        void update(int x,int l,int r,int ql,int qr,int value){
        	if(ql <= l && qr >= r){
        		tree[x] += value;
        		tag[x] += value;
        		return;
        	}
        	int mid = (l+r)>>1;
        	push_down(x);
        	if(ql <= mid){
        		update(lc(x),l,mid,ql,qr,value);
        	}
        	if(qr > mid){
        		update(rc(x),mid+1,r,ql,qr,value);
        	}
        	push_up(x);
        }
        
        • 1

        信息

        ID
        137
        时间
        1000ms
        内存
        125MiB
        难度
        5
        标签
        递交数
        83
        已通过
        35
        上传者