牛客CSP-S提高组赛前集训营2

牛客CSP-S提高组赛前集训营2

T1 服务器需求

服务器需求
假如没有修改
很明显答案就是\(max(a_i,\lceil{sum/m}\rceil)\)
带修??
multiset过掉
没开\(long\) \(long\)见了一次祖宗

#include<bits/stdc++.h>
#define ll long long
#define int long long
using namespace std;
const int maxn=4*1e5+10;
int n,m,q,a[maxn];
ll sgm=0;
multiset<ll,greater<ll> > st;
signed main()
{
    scanf("%lld%lld%lld",&n,&m,&q);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]),sgm+=a[i],st.insert(a[i]);
    ll maxx=(sgm+(m-1))/m;
    maxx=max(maxx,*st.begin());
    printf("%lld\n",maxx);
    while(q--){
        int x,y;scanf("%lld%lld",&x,&y);
        st.erase(st.find(a[x]));sgm-=a[x];
        st.insert(y);a[x]=y;sgm+=a[x];
        maxx=max((sgm+(m-1))/m,(ll)*st.begin());
        printf("%lld\n",maxx);
    }
    return 0;
}

T2 沙漠点列

沙漠点列
一眼看上去割边
但是剩下连通块的简单环的怎么办
只能多消耗一次去先断环,然后剩下的都是割边
可以用桶找最大环
先爆栈又忘了判断大于零见了一上午祖宗

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2*1e6+10;
int n,m,k,head[maxn],tot=1,ans,to[maxn<<1];
struct node{
	int nxt,to;
	#define nxt(x) e[x].nxt
	#define to(x) e[x].to
}e[maxn<<1];
inline void add(int from,int to){
	to(++tot)=to;nxt(tot)=head[from];head[from]=tot;
}
int dfn[maxn],low[maxn],num,rt,br[maxn<<1],maxx,cut;
void tarjan(int x,int in){
	dfn[x]=low[x]=++num;
	for(int i=head[x];i;i=nxt(i)){
		int y=to(i);
		if(!dfn[y]){
			tarjan(y,i);
			low[x]=min(low[x],low[y]);
			if(low[y]>dfn[x]){
				br[i]=br[i^1]=1,cut++;
			}
		}else if(i!=(in^1)) low[x]=min(low[x],dfn[y]);
	}
}
int ds[maxn];
inline void search(int x,int fa){
	ds[x]=ds[fa]+1;
	for(int i=head[x];i;i=nxt(i)){
		int y=to(i);
		if(y==fa || br[i]) continue;
		if(ds[y]){
			to[max(ds[x]-ds[y]+1,(int)0)]++;maxx=max(maxx,ds[x]-ds[y]+1);continue;
		}
		search(y,x);
	}
}
signed main()
{
	scanf("%lld%lld%lld",&n,&m,&k);
	for(int x,y,i=1;i<=m;i++){
		scanf("%lld%lld",&x,&y);add(x,y);add(y,x);
	}
	for(int i=1;i<=n;i++) if(!dfn[i]) tarjan(i,0),ans++;
	if(cut>=k){
		printf("%lld\n",ans+k);return 0;
	}
	k-=cut;ans+=cut;
	for(int i=1;i<=n;i++) if(!ds[i]) search(i,0);
	for(int len=maxx;len;len--) if(to[len]){
		while(to[len]){
			to[len]--;int x=len;k--;
			if(!k){
				printf("%lld\n",ans);return 0;
			}
			if(k<=x-1){
				printf("%lld\n",ans+k);return 0;
			}
			k-=x-1;ans+=x-1;
		}
	}
	printf("%lld\n",ans);
	return 0;
}

T3 ?????

咕咕咕?????

posted @ 2019-11-01 11:55  ChrisKKK  阅读(171)  评论(0编辑  收藏  举报