LOADING

加载过慢请开启缓存,浏览器默认开启

daily 1

2023/4/11 daily

老子就不信老子调整不过来了,操,又玩了一天

CF 79D

先把对应的序列取一个异或差分
那么我们的最终目标就是把差分数组变为全0

为了这个目的,我们可以这样理解,一次对应的操作就是把对应的${b{l-1}}$取反,然后把${b{r}}$取反

那么我们可以把这个问题抽象成一个最短路的问题,因为我们需要找到两个为1的位置,然后把这两个位置都变成0

因此我们对每个为1的位置做dij

之后就是常规的妆呀dp啦

void solve(){
  int n,k,l;
  cin>>n>>k>>l;
  vector<int>x(k+1),a(n+2),len(l+1),id(n+1);
  for(int i=1;i<=k;++i){
    cin>>x[i];
    a[x[i]]=1;
  }
  for(int i=1;i<=l;++i){
    cin>>len[i];
  }
  int cnt=0;
  for(int i=0;i<=n;++i){
    a[i]^=a[i+1];
    id[i]=a[i]?cnt++:0;
  }
  vector dist(cnt+1,vector<int>(cnt+1));
  vector<int>dis(n+1,INF);
  vector<int>vis(n+1,0);
  auto dij=[&](int st){ 
    fill(dis.begin(),dis.end(),INF);
    fill(vis.begin(),vis.end(),0);
    dis[st]=0;
    vis[st]=1;
    queue<int>q;
    q.push(st);
    while(!q.empty()){
      int now=q.front();
      q.pop();
      for(int i=1;i<=l;++i){
        int d1=now+len[i],d2=now-len[i];
        if(d1<=n&&!vis[d1]){
          dis[d1]=dis[now]+1;
          vis[d1]=1;
          q.push(d1);
        }
        if(d2>=0&&!vis[d2]){
          dis[d2]=dis[now]+1;
          vis[d2]=1;
          q.push(d2);
        }
      } 
    }
    for(int i=0;i<=n;++i){
      if(a[i])dist[id[st]][id[i]]=dis[i];
    }
  };
  for(int i=0;i<=n;++i){
    if(a[i])dij(i);
  }
  vector<int>dp((1<<cnt));
  for(int status=1;status<(1<<cnt);++status){
    dp[status]=INF;
    for(int i=0;i<cnt;++i){
      if(!((status>>i)&1))continue;
      for(int j=i+1;j<cnt;++j){
        if(!((status>>j)&1))continue;
        dp[status]=min(dp[status],dp[status-(1<<i)-(1<<j)]+dist[i][j]);
      }
    }
  }
  cout<<(dp[(1<<cnt)-1]==INF?-1:dp[(1<<cnt)-1])<<'\n';
  return;
}