• Codeforces 626G. Raffles 题解


    题目链接:G. Raffles

    题目大意:洛谷


    题解:考虑将每一个增加的式子列出来 (p_i(frac{t_i+1}{t_i+l_i+1} -frac{t_i}{t_i+l_i}) = frac{p_i l_i}{(t_i+l_i)(t_i+l_i+1)}) ,因为贡献递减,所以我们可以按照增加的价值排序,然后从大到小取,单次的时间复杂度 (O(n log n))

    然后考虑多次询问,每一次将原来的数暴力删掉在重新加进去,然后这个可以用 set 维护,随后直接暴力退出当前在内部的最小值和加入当前不在内部的最大值,这也可以用 set 维护,因为每一次只会改变 1,所以每一次的加入和删除的次数是 (O(1)) 的。

    总时间复杂度 (O(nlog n))(n,t,q)同级)。

    代码:

    #include <set>
    #include <cmath>
    #include <cstdio>
    using namespace std;
    const int Maxn=200000;
    const double Inf=1e18;
    const double eps=1e-10;
    int n,t,q;
    int p[Maxn+5],l[Maxn+5],c[Maxn+5];
    double f(int x,int c){
    	if(c==-1){
    		return Inf;
    	}
    	if(c>=l[x]){
    		return 0.0;
    	}
    	return 1.0*p[x]*l[x]/(c+1+l[x])/(c+l[x]);
    }
    double g(int x){
    	return 1.0*p[x]*min(c[x],l[x])/(min(c[x],l[x])+l[x]);
    }
    struct Node{
    	double val;
    	int x,c;
    	Node(int _x=0,int _c=-1){
    		x=_x;
    		c=_c;
    		val=f(x,c);
    	}
    	friend bool operator <(Node a,Node b){
    		if(fabs(a.val-b.val)>eps){
    			return a.val<b.val;
    		}
    		return a.x<b.x;
    	}
    };
    set<Node> nxt,used;
    double ans;
    void add(){
    	set<Node>::iterator it=(--nxt.end());
    	ans+=(it->val);
    	int x=(it->x);
    	used.erase(Node(x,c[x]-1));
    	used.insert(*it);
    	nxt.erase(it);
    	nxt.insert(Node(x,++c[x]));
    }
    void del(){
    	set<Node>::iterator it=used.begin();
    	ans-=(it->val);
    	int x=(it->x);
    	nxt.erase(Node(x,c[x]));
    	nxt.insert(*it);
    	used.erase(it);
    	used.insert(Node(x,(--c[x])-1));
    }
    int main(){
    	scanf("%d%d%d",&n,&t,&q);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&p[i]);
    	}
    	for(int i=1;i<=n;i++){
    		scanf("%d",&l[i]);
    		nxt.insert(Node(i,0));
    		used.insert(Node(i));
    	}
    	while(t--){
    		add();
    	}
    	for(int i=1;i<=q;i++){
    		int op,x;
    		scanf("%d%d",&op,&x);
    		op=(op==1?1:-1);
    		nxt.erase(Node(x,c[x]));
    		used.erase(Node(x,c[x]-1));
    		ans-=g(x);
    		l[x]+=op;
    		nxt.insert(Node(x,c[x]));
    		used.insert(Node(x,c[x]-1));
    		ans+=g(x);
    		while(((--nxt.end())->val)>((used.begin()->val)+eps)){
    			del();
    			add();
    		}
    		printf("%.7lf
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    异常处理
    SPD各模块总结
    简易js调试
    深入理解:java类加载器
    java基础简介
    android四大组件(一)Activity
    网路编程(网站源码查看器)
    ListView
    SQL查询数据总结
    函数作用域中的this问题
  • 原文地址:https://www.cnblogs.com/withhope/p/13680032.html
Copyright © 2020-2023  润新知