首页 > 其他分享 >CF939D

CF939D

时间:2024-09-03 16:06:15浏览次数:10  
标签:int 区间 back dfs push put CF939D

比较好的构造题

首先数据范围为 \(18\) ,令人浮想联翩:状压

有一个性质就是我们可以在一定操作内把一段区间的数全部变成 \(0\) ~ \(r-l\) ,再全部变成 \(r-l+1\)

具体的,对于一段区间 \(l,r\) 变成 \(0\) ~ \((r-l+1)\)

  1. 先把 \(l,r-1\) 变为 \(0\) ~ \((r-l)\) ,
  2. 然后判断 \(a_r\) 是否是 \(r-l+1\),如果 不是 则把 \(l,r\) 全都变成 \(r-l+1\) ,
  3. 然后再把 \(l,r-1\) 变为 \(0\) ~ \((r-l)\) 但是要注意,这一次变的过程不能再进行第 \(2\) 步,因为这个区间所有数已经变成了 \(r-l+1\)
void dfs(int l,int r,int f)
{
    if(l==r) 
    {
        if(f==0||a[l]!=0) put.push_back({l+1,r+1});
        return;
    }
    dfs(l,r-1,f);
    if(f==0||a[r]!=r-l)
    {
        put.push_back({l+1,r+1});
        dfs(l,r-1,0);
    }
}

继续分析问题,发现有一些数变更划算,有些数不变更划算,列如 \(1000\) 这个数

发现不方便直接贪心看每个数是否变,所以考虑二进制枚举不变的数,剩下的数要变

再次发现对于一段完整的要变的区间,一起变显然更有性价比

即不变的数把原序列分割成了多个区间,对于每个要变区间进行变换

则问题得到解决

#include<bits/stdc++.h>
using namespace std;
const int N=19;
int a[N];
vector<pair<int,int> > put;
void dfs(int l,int r,int f)
{
    if(l==r) 
    {
        if(f==0||a[l]!=0) put.push_back({l+1,r+1});
        return;
    }
    dfs(l,r-1,f);
    if(f==0||a[r]!=r-l)
    {
        put.push_back({l+1,r+1});
        dfs(l,r-1,0);
    }
}
int main()
{
    int n;
    cin>>n;
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    int ans=0;
    int id=0;
    for(int i=0;i<(1<<n);i++)
    {
        int cnt=0;
        for(int j=0;j<n;j++)
        {
            if(i>>j&1) cnt+=a[j];
            else
            {
                int k=j;
                while(k<n&&!(i>>k&1)) k++;
                cnt+=(k-j)*(k-j);
                j=k-1;
            }
        }
        if(ans<cnt)
        {
            ans=cnt;
            id=i;
        }
    }
    //cout<<id<<"\n";
    for(int i=0;i<n;i++)
    {
        if(!(id>>i&1))
        {
            int j=i;
            while(j<n&&!(id>>j&1)) 
            {
                j++;
            }
            //cout<<i<<" "<<j<<"\n";
            dfs(i,j-1,1);
            put.push_back({i+1,j});
            i=j-1;
        }
    }
    cout<<ans<<" "<<put.size()<<"\n";
    for(auto i:put) printf("%d %d\n",i.first,i.second);
}

标签:int,区间,back,dfs,push,put,CF939D
From: https://www.cnblogs.com/Oistream/p/18394774

相关文章