zoukankan      html  css  js  c++  java
  • [CF1526C] Potions

    前言

    这道题我两年前直接爆切,两年后碰到类似的题:数据结构。

    降智严重啊。

    题目

    CF

    题目大意:

    (n) 瓶药剂,从左往右编号依次是 (1...n),每瓶药剂有一个值 (a_i) ,表示喝下去之后你可以增加 (a_i) 点生命值((a_i) 为负则是减少生命值)。你的初始生命值为 (0),从左往右依次选择药剂喝掉(当然也可以不喝),询问最多可以喝多少药剂。过程中要保证生命值不低于0

    (1le nle 200000;-10^9le a_ile 10^9.)

    讲解

    这里有一个优秀的反悔贪心做法。

    只要喝不死,就往死里喝。如果喝死了,就把最毒的吐出来!

    显然这是正确的,而且只需要一个优先队列即可简单实现。

    还有一个蠢一点的做法:先把所有不扣血的药剂全部喝光,得到每个位置的最大生命值。然后贪心选毒性最小的药剂喝掉,用线段树维护是否会毒死。

    不过这样实现十分冗长。

    代码

    std

    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
    	ios_base::sync_with_stdio(false); cin.tie(0);
    	
    	int n; cin >> n;
    	priority_queue<long long, vector<long long>, greater<long long> > pq;
    	long long S = 0;
    	
    	for(int i = 1;i <= n;i++){
    		long long x; cin >> x;
    		S += x;
    		pq.push(x);
    		
    		while(S < 0){
    			S -= pq.top();
    			pq.pop();
    		}
    	}
    	
    	cout << (int) pq.size();
    }
    

    我就是这个做法...

    int h;
    struct node
    {
    	int val,ID;
    	bool operator < (const node &px)const{
    		if(val != px.val) return val > px.val;
    		return ID > px.ID;
    	}
    }s[MAXN];
    
    #define lc (x<<1)
    #define rc (x<<1|1)
    struct SegmentTree
    {
    	LL MIN[MAXN << 2],lz[MAXN << 2];
    	
    	void up(int x){MIN[x] = Min(MIN[lc],MIN[rc]);}
    	
    	void down(int x){
    		if(!lz[x]) return;
    		lz[lc] += lz[x];
    		lz[rc] += lz[x];
    		MIN[lc] += lz[x];
    		MIN[rc] += lz[x];
    		lz[x] = 0;
    		return;
    	}
    	
    	void Build(int x,int l,int r)
    	{
    		if(l == r) {MIN[x] = a[l];lz[x] = 0;return;}
    		int mid = (l+r) >> 1;
    		Build(lc,l,mid); Build(rc,mid+1,r);
    		up(x);
    	}
    	
    	void Add(int x,int l,int r,int ql,int qr,LL val)
    	{
    		if(ql <= l && r <= qr) {MIN[x] += val;lz[x] += val;return ;}
    		down(x);
    		int mid = (l+r) >> 1;
    		if(ql <= mid) Add(lc,l,mid,ql,qr,val);
    		if(mid+1 <= qr) Add(rc,mid+1,r,ql,qr,val);
    		up(x);
    	}
    	
    	LL Query(int x,int l,int r,int ql,int qr)
    	{
    		if(ql <= l && r <= qr) return MIN[x];
    		down(x);
    		LL mid = (l+r) >> 1,ret = INF;
    		if(ql <= mid) ret = Min(ret,Query(lc,l,mid,ql,qr));
    		if(mid+1 <= qr) ret = Min(ret,Query(rc,mid+1,r,ql,qr));
    		return ret;
    	}
    }st;
    
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	n = Read();
    	for(int i = 1;i <= n;++ i) 
    	{
    		a[i] = Read(); 
    		if(a[i] >= 0) ans++,S += a[i],a[i] = S;
    		else s[++h].val = a[i],s[h].ID = i,a[i] = S;
    	}
    	st.Build(1,1,n);
    	sort(s+1,s+h+1);
    	for(int i = 1;i <= h;++ i)
    	{
    		LL M = st.Query(1,1,n,s[i].ID,n);
    		if(M < Abs(s[i].val)) continue;
    		ans++;
    		st.Add(1,1,n,s[i].ID,n,s[i].val);
    	}
    	Put(ans);
    	return 0;
    }
    
  • 相关阅读:
    callable函数,检查对象是否可调用
    eval函数的一些用法
    divmod函数使用
    sorted(x, reverse=True)
    列表、元组、字典空格的几种移除方法
    约瑟夫环问题(通过观察得出递推式从而建立递归求解)
    快速幂算法(二分思想减少连乘次数)
    素数筛(埃氏筛法与欧拉筛)
    KMP算法的详细解释
    对于线性代数的形象化理解(1)
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/14827064.html
Copyright © 2011-2022 走看看