A.-Grass Field
找规律 四种情况 一行一列最多能除三个草
void solve(){
int cnt=0;
for(int i=1;i<=2;i++){
for(int j=1;j<=2;j++)
{
int x;
cin>>x;
if(x==1)cnt++;
}
}
if(cnt==0)cout<<"0"<<endl;
else if(cnt<4)cout<<1<<endl;
else cout<<2<<endl;
}
无论n是多少 当d=2时他取到最大的价值,当且仅当n=3时 d=3和d=2取到相同的价值,特判就行了
void solve(){
cin>>n;
if(n==2){
cout<<2<<endl;
cout<<1<<" "<<2<<endl;
return ;
}
if(n==3){
cout<<3<<endl;
cout<<2<<" "<<1<<" "<<" "<<3<<endl;
}
else {
map<int,int>st;
cout<<2<<endl;
cout<<1<<" ";
for(int j=2;j<=n;j++){
for(int i=j;i<=n;i*=2){
if(!st[i])cout<<i<<" ",st[i]=1;
}
}
cout<<endl;
}
}
这个时间有一定的范围 最多是2*m 我们从1-2*m的范围对他进行暴力二分就可以了
把没有出现过的a[i]记录起来 每一个没出现过在mid的时间内,能完成的任务数量是
mid/2,而比mid小的a[i]在mid时间内能完成的任务数量是(mid-a[i])/2,依照这样进行check
bool check(int x){
int kk=0;
int res=0;
for(int i=1;i<=n;i++){
if(!mp[i])kk+=x/2;
if(mp[i]>x){
res+=(mp[i]-x);
}
else if(mp[i]<x&&mp[i]) kk+=(x-mp[i])/2;
}
if(kk>=res)return true;
return false;
}
void solve(){
mp.clear();
cin>>n>>m;
fo(i,1,m){
int x;
cin>>x;
mp[x]++;
}
int l=1,r=m;
while(l<r){
int mid=(l+r)>>1;
if(check(mid))r=mid;
else l=mid+1;
}
cout<<r<<endl;
}
观察一下b b=i/a[i] 找到每个b对应的a[i]的范围,将b的按先右端点后左端点的顺序排列,每次都从1-n里面抽取b需要的最小左边界 就可以得到一个合法的 a[i]
边界 r=a[i]/b l=a[i]/(b+1)+1
bool cmp(node a,node b){
return a.r==b.r?a.l<b.l:a.r<b.r;
}
void solve(){
set<int>st;
cin>>n;
fo(i,1,n){
cin>>a[i];
e[i].id=i;
st.insert(i);
}
fo(i,1,n){
if(a[i]==0){
e[i].l=i+1,e[i].r=n;
}
else{
e[i].r=i/a[i];
e[i].l=i/(a[i]+1)+1;
}
}
sort(e+1,e+1+n,cmp);
for(int i=1;i<=n;i++){
p[e[i].id]=*st.lower_bound(e[i].l);
st.erase(p[e[i].id]);
}
for(int i=1;i<=n;i++)cout<<p[i]<<" ";
cout<<endl;
}