Codeforces 1091E New Year and the Acquaintance Estimation Erdős–Gallai定理

 题目链接:E - New Year and the Acquaintance Estimation

题解参考:

Havel–Hakimi algorithm 和 Erdős–Gallai theorem

按照后面那个定理说的,枚举$k∈[1,n]$,对于每一个$k$,计算出向等式两边加入$a_{n+1}$的合法范围,最后所有范围求交即可

最后按照前面那个定理说的,枚举最终区间的时候,对于合法真正的$a_{n+1}$进行输出即可

比赛的时候没看见后面那个定理,推了半天

-----------------------

正常人写法:

#include <bits/stdc++.h>
#define ll long long
#define rep(ii,a,b) for(ll ii=a;ii<=b;++ii)
using namespace std;
int n;
int main() {
	ios::sync_with_stdio(false);cin.tie(0);
	cin>>n;
	vector<ll>deg(n),sum(n+1);
	for(auto&i:deg) cin>>i;
	sort(deg.begin(),deg.end());
	rep(i,0,n-1) sum[i+1]=sum[i]+deg[i];
	int pos=0;
	ll lower=-1,upper=n+2;
	rep(k,1,n){
    while(pos<n&&deg[pos]<k) pos++;
    ll uper=min(n-k,(ll)pos);
    ll eql=sum[n]-sum[n-k];
		ll eqr=k*(k-1)+sum[uper]+k*(n-k-uper);
		ll amin=eql-eqr;
		ll amax=eqr-eql+deg[n-k]+min(deg[n-k],(ll)k);
		lower=max(amin,lower);
		upper=min(amax,upper);
	}
	if(upper-lower<0) cout<<-1;
	else rep(i,lower,upper) if((sum[n]+i)%2==0) cout<<i<<' ';
}

  

 弱智写法:

#include <bits/stdc++.h>
#define ll long long
#define rep(ii,a,b) for(ll ii=a;ii<=b;++ii)
using namespace std;
int n;
class segtree{
#define nd  node[now]
#define ndl node[now<<1]
#define ndr node[now<<1|1]
	public:
	struct segnode {
		int l,r,mx,tag;
		int mid(){return (r+l)>>1;}
		int len(){return r-l+1;}
		void update(int x){mx+=x,tag+=x;}
	};
	vector<segnode> node;
	segtree(int n) {node.resize(n<<2|3);maketree(1,n);}
	void pushup(int now){nd.mx=max(ndl.mx,ndr.mx);}
	void pushdown(int now){
		if(nd.tag){
			ndl.update(nd.tag);
			ndr.update(nd.tag);
			nd.tag=0;
		}
	}
	void maketree(int s,int t,int now=1){
		nd={s,t,0,0};
		if(s==t)return ;
		maketree(s,(s+t)>>1,now<<1); maketree(((s+t)>>1)+1,t,now<<1|1);
	}
	void update(int s,int t,int x,int now=1){
		if(s>nd.r||t<nd.l) return ;
		if(s<=nd.l&&t>=nd.r){
			nd.update(x);
			return ;
		}
		pushdown(now);
		update(s,t,x,now<<1); update(s,t,x,now<<1|1);
		pushup(now);
	}
	int query_lowerbound(int now=1){
		if(nd.mx<n) return -1;
		if(nd.len()==1) return nd.l;
		pushdown(now);
		if(ndl.mx>=n) return query_lowerbound(now<<1);
		else return query_lowerbound(now<<1|1);
	}
	int query_upperbound(int now=1){
		if(nd.mx<n) return -1;
		if(nd.len()==1) return nd.l;
		pushdown(now);
		if(ndr.mx>=n)return query_upperbound(now<<1|1);
		else return query_upperbound(now<<1);
	}
#undef nd
#undef ndl
#undef ndr
};
int main() {
	ios::sync_with_stdio(false);cin.tie(0);
	cin>>n;
	segtree tree(n);
	vector<ll>deg(n),sum(n+1);
	for(auto&i:deg) cin>>i;
	sort(deg.begin(),deg.end());
	rep(i,0,n-1) sum[i+1]=sum[i]+deg[i];
	int pos=0;
	rep(k,1,n){
    while(pos<n&&deg[pos]<k) pos++;
    ll uper=min(n-k,(ll)pos);
    ll eql=sum[n]-sum[n-k];
		ll eqr=k*(k-1)+sum[uper]+k*(n-k-uper);
		ll amin=eql-eqr;
		ll amax=eqr-eql+deg[n-k]+min(deg[n-k],(ll)k);
		if(amin<=min(k,deg[n-k])) tree.update(max(amin,0ll),deg[n-k],1);
		if(amax>deg[n-k]) tree.update(deg[n-k]+1,min(amax,(ll)n),1);
	}
	int lower=tree.query_lowerbound(),upper=tree.query_upperbound();
	if(lower==-1) cout<<-1;
	else rep(i,lower,upper)if((sum[n]+i)%2==0) cout<<i<<' ';
}

  

posted @ 2019-01-04 21:07  nervending  阅读(527)  评论(0编辑  收藏  举报