zoukankan      html  css  js  c++  java
  • LuoguP6619 省选联考 2020 A/B 卷 冰火战士(树状数组)

      是不是快一年没写代码了啊?省选送分题现在得做一年。有没有学上先不管了。

      容易发现总能量计算方式是两队被选出的参赛者各自能量和的min。显然随场地温度升高,冰队能量和单增,火队能量和单减,在两者最接近时总能量应最大。那么对冰队<=火队和冰队>=火队分别找到最大总能量及对应温度即可,可以二分+树状数组处理,log方T掉。

      由树状数组的原理可以得到在树状数组上二分的方法。比如要找到满足某个条件的最长前缀,可以按二进制位从高到低枚举,假设当前找到的最长前缀为x,如果加上当前二进制位1<<i后仍满足条件,前缀就可以增长至x+(1<<i),x+1~x+(1<<i)这段的信息就存在树状数组的[x+(1<<i)]中。于是用树状数组二分替换二分+树状数组即可。

      有一些细节大约可以参考代码,并不知道写得简不简便。

    #include<bits/stdc++.h>
    using namespace std;
    #define N 2000010
    #define inf 2000000000
    int T,cnt,w[N],v[N],tree[2][N],tot;
    struct data{int op,team,T,E;
    }a[N];
    int read()
    {
    	int x=0;char c=getchar();
    	while (c<'0'||c>'9') c=getchar();
    	while (c>='0'&&c<='9') x=x*10+c-48,c=getchar();
    	return x;
    }
    void add(int team,int k,int x){while (k<=cnt) tree[team][k]+=x,k+=k&-k;}
    int sum(int team,int k){int s=0;while (k) s+=tree[team][k],k-=k&-k;return s;}
    int main()
    {
    	T=read();
    	for (int i=1;i<=T;i++)
    	{
    		a[i].op=read();
    		if (a[i].op==1) a[i].team=read(),w[++cnt]=a[i].T=read(),a[i].E=read();
    		else a[i].team=read();
    	}
    	sort(w+1,w+cnt+1);
    	int t=unique(w+1,w+cnt+1)-w-1;
    	for (int i=1;i<=T;i++) if (a[i].op) a[i].T=lower_bound(w+1,w+t+1,a[i].T)-w+a[i].team;
    	cnt=t;w[++cnt]=inf;
    	//for (int i=1;i<=T;i++) cout<<a[i].T<<endl;
    	for (int i=1;i<=T;i++)
    	{
    		if (a[i].op==1) add(a[i].team,a[i].T,a[i].E),tot+=a[i].team*a[i].E;
    		else
    		{
    			int x=a[i].team;
    			add(a[x].team,a[x].T,-a[x].E),tot-=a[x].team*a[x].E;
    		}
    		int x=0,u=0,v=tot;
    		for (int j=20;j>=0;j--)
    		if (x+(1<<j)<=cnt&&u+tree[0][x+(1<<j)]<=v-tree[1][x+(1<<j)])
    		x+=1<<j,u+=tree[0][x],v-=tree[1][x];
    		//cout<<w[x]<<' '<<u<<' '<<v<<endl;
    		int t=tot-sum(1,x+1);
    		if (t>=u)
    		{
    			u=t;x=0;int s=tot;
    			for (int j=20;j>=0;j--)
    			if (x+(1<<j)<=cnt&&s-tree[1][x+(1<<j)]>=t) x+=1<<j,s-=tree[1][x];
    		}
    		if (u==0) printf("Peace
    ");
    		else printf("%d %d
    ",w[x],u*2);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    程序修炼之道——从小工到专家(3)
    组合
    子类重用父类的功能
    对象之间的交互
    属性查找与绑定方法
    类与对象的定义与使用
    hashlib模块subprocess模块
    configerparser模块
    shelve模块 xml模块
    sys模块 json pickle模块
  • 原文地址:https://www.cnblogs.com/Gloid/p/13290235.html
Copyright © 2011-2022 走看看