zoukankan      html  css  js  c++  java
  • 星空[好题][题意转化]

    题目大意:给你一个0/1串,让你对区间亦或(有特定几个长度限制操作),最后让你求出把这个0/1串变成全0串的最小操作数;

    前置问题:

    首先发现对原序列区间整体亦或很不好控制,因为会不断出现新的1;

    那我们怎么办?

    想想差分;

    与普通线性数组差分一样,若原序列有初始值,则需要把原序列转化为差分序列;

    具体求法即为:b[i]=a[i]-a[i-1];(b数组为差分数组,a为原数组)

    同理亦或差分:b[i]=a[i]^a[i-1];

    于是我们可以把原序列转化成为差分序列;

    那我们为什么要把元序列转化为差分序列呢?

    {

      1.考虑区间修改,元序列有0与1相互转化,并会蹦出新的1;

      2.而差分数组只对两端进行修改;只有0/1的单次转化;

      3.最重要的性质,差分数组与原数组的最终状态一直,都是全0串;(若 原序列为000000000 ,亦或差分序列不也得是00000000吗)

    }

    一-------于是成功转化题意;

    在原序列的差分序列上进行如下操作:

    1.把可把1在序列上向左移动或向右移动几种固定长度,当1与1想碰时变为0;

    2.求最终把这个序列变为全0串的最小操作数;

    eg.差分序列:000110001100   区间修改就是选区间的左右端点(不严谨),然后对两个端点亦或,这不就是把左端点1亦或成0,而右端点0亦或成1吗;其实就是把1移动......

    那这样就很好做了;

    既然有固定的长度;那就把长度看成边;

    把差分序列上的每个点都和他能一次操作到达的点连边;而边权就是1;一部操作吗.......

    二-------于是就形成了一个图;

    而我们要知道的就是1之间互相到达的代价;在图中转化为距离;

    那就跑dijistrla呗;只不过得跑2k次;

    但没关系啊;NlogN*2k完全可以;

    一波dijistrla后,我们求出了dis[i][j] 代表的是差分序列上 第i个1 到 第j个1的 代价;

    三-------于是问题又转化了:

    你有2k个物品,两两能以一定代价互相匹配,求把这2k个物品分为k对的最小代价;

    而k<=8;2k<=16;

    状压呗;O((k^2)*(2^2k))可以卡过;

    最终状态就是(1<<2k)-1;

    附上自带常数的代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define rd(x) scanf("%lld",&x)
     4 #define int long long
     5 int a[400050],b[400050],edge[1000],pos[100],id[400050];
     6 int N,K,M;
     7 int dis[100][100];
     8 int f[1<<20|1],g[100][100];
     9 vector<int>to[400500];
    10 
    11 struct node{
    12     int to,dis;
    13     node(int a,int b){to=a;dis=b;}
    14     friend bool operator<(node a,node b){
    15         return a.dis>b.dis;
    16     }
    17 };
    18 
    19 bool v[40050];
    20 int d[40050];
    21 void diji(int st){
    22     priority_queue<node>q;
    23     memset(d,0x3f,sizeof(d));memset(v,0,sizeof(v));
    24     d[st]=0;q.push(node(st,d[st]));
    25     register int u,w;
    26     while(q.size()){
    27         u=q.top().to;w=q.top().dis;q.pop();
    28         if(v[u])continue;
    29         v[u]=1;
    30         for(register int i=0,y;i<to[u].size();++i){
    31             y=to[u][i];
    32             if(v[y])continue;
    33             if(d[u]+1<d[y]){
    34                 d[y]=d[u]+1;
    35                 q.push(node(y,d[y]));
    36             }
    37         }
    38     }
    39     for(int i=1;i<=pos[0];++i)
    40     if(id[i]!=st){
    41         dis[id[st]][i]=dis[i][id[st]]=d[pos[i]];
    42     }
    43 }
    44 
    45 signed main(){
    46     rd(N);rd(K);rd(M);
    47     for(register int i=1,p;i<=K;++i){
    48         rd(p);a[p]=1;
    49     }
    50     for(register int i=1;i<=M;++i){
    51         rd(edge[i]);
    52     }
    53     for(register int i=1;i<=N;++i){
    54         for(register int j=1;j<=M;++j){
    55             if(i+edge[j]>N+1)break;
    56             to[i].push_back(i+edge[j]);
    57             to[i+edge[j]].push_back(i);
    58         }
    59     }
    60     for(register int i=1;i<=N+1;++i){
    61         b[i]=a[i]^a[i-1];
    62         if(b[i])pos[++pos[0]]=i,id[i]=pos[0];
    63     }
    64     for(register int i=1;i<=pos[0]-1;++i)diji(pos[i]);
    65     /*for(int i=1;i<=pos[0];++i){
    66         for(int j=1;j<=pos[0];++j)cout<<dis[i][j]<<" ";
    67         cout<<endl;
    68     }*/
    69     for(register int i=1;i<=pos[0];++i)
    70         for(register int j=1;j<=pos[0];++j)
    71             if(i!=j)g[i][j]=(1<<i-1)|(1<<j-1);
    72     memset(f,0x3f,sizeof(f));register int Z=(1<<pos[0])-1;
    73     f[0]=0;
    74     for(register int i=0;i<=Z;++i)
    75     {
    76         if(i==Z)break;
    77         for(register int j=1;j<=pos[0];++j)
    78         if((i&(1<<j-1))==0){
    79             for(register int k=j+1;k<=pos[0];++k)
    80             if((i&(1<<k-1))==0){
    81                 f[i|g[j][k]]=min(f[i|g[j][k]],f[i]+dis[j][k]);
    82             }
    83         }
    84 
    85     }
    86     printf("%lld
    ",f[Z]);
    87 }
    自带常数爆炸
  • 相关阅读:
    vim encoding
    window线程间通信常用的三种方法
    Python与C之间的相互调用(Python C API及Python ctypes库)
    vim中去掉每一行的^M
    现实点,不要急! [ 公司软件过程改进案例]
    理解TCP/IP协议
    Linux下C/C++帮助手册安装方法 及使用方法
    MySQL主主高可用(keepalive)
    React获取DOM元素ref属性
    一些vue组件库
  • 原文地址:https://www.cnblogs.com/wang-hesong/p/11335472.html
Copyright © 2011-2022 走看看