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&°[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&°[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<<' '; }