zoukankan      html  css  js  c++  java
  • [loj3301]魔法商店

    令$A={a_{1},a_{2},...,a_{s}}$,若$k otin A$,那么恰存在一个$A'subseteq A$使得$c_{k}=igoplus_{xin A'}c_{x}$

    存在性:若不存在,将$k$加入$A$中仍然为合法的集合,与$|A|$最大矛盾

    唯一性:若存在多个,将其中两个集合异或(即保留在这两个集合中出现奇数次的元素),显然这个异或的结果非空且所有元素异或和为0,与$A$为合法的集合矛盾

    (为了方便,称$A'$为$k$的表示集合)

    此时,限制即$forall k otin A$且$xin A',v_{x}le v_{k}$(其中$A'$为$k$的表示集合)

    必要性:若不满足此性质,显然用$k$替换$x$价格和更小

    充分性:考虑合法方案$B$,满足$|B|=|A|$,来证明$sum_{xin A}v_{x}le sum_{xin B}v_{x}$

    考虑$kin A$且$k otin B$,同理恰存在一个$B'subseteq B$使得$c_{k}=igoplus_{xin B'}c_{x}$

    若$forall xin B'$且$x otin A$,其的表示集合若包含$k$,那么即有$v_{k}le v_{x}$,用$k$替换$x$不劣

    若所有$x$的表示集合都不包含$k$,那么将这些表示集合和$(Acap B')cup{k}$异或,显然这个异或的结果非空($k$必然只出现一次)且所有元素异或和为0,矛盾

    因此,重复此过程,每一次$|Acap B|$恰好增加1,那么必然会有$|Acap B|=|A|=|B|$,也即$A=B$

    关于如何求$A'$可以使用线性基,复杂度为$o(nm)$(实现中比较懒用了$o(frac{n^{2}m}{omega})$)

    (关于价格和最大的方案类似,也可以得到若干个不等式)

    得到不等式后,即是一个保序回归的问题,做法参考[tc14634]ExtremeSpanningTrees

    (另外,其中的引理中$S$应改为$[0,10^{6}]$,因为是平方,所以加1的答案增加$Delta$但减1不一定使答案增加$-Delta$)

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define N 1005
      4 #define M 105
      5 #define ll unsigned long long
      6 #define oo 0x3f3f3f3f
      7 #define vi vector<int>
      8 struct ji{
      9     int nex,to;
     10     ll len;
     11 }edge[N*M*4];
     12 queue<int>q;
     13 bitset<N>BT,bt[M];
     14 int E,n,m,x,w[N],vis[N],head[N],work[N],a[N],d[N],bl[N],ans[N],lim[N][N];
     15 ll sum,c[N],val[M];
     16 void add(ll k,int x){
     17     ll o=1;
     18     BT.reset();
     19     BT[x]=1;
     20     for(int i=63;i>=0;i--)
     21         if (k&(o<<i)){
     22             if (!val[i]){
     23                 val[i]=k;
     24                 bt[i]=BT;
     25             }
     26             k^=val[i];
     27             BT^=bt[i];
     28         }
     29 }
     30 void query(ll k,int x,int p){
     31     ll o=1;
     32     BT.reset();
     33     for(int i=63;i>=0;i--)
     34         if (k&(o<<i)){
     35             BT^=bt[i];
     36             k^=val[i];
     37         }
     38     for(int i=1;i<=n;i++)
     39         if (BT[i]){
     40             if (!p)lim[i][x]=1;
     41             else lim[x][i]=1;
     42         }
     43 }
     44 ll sqr(ll k){
     45     return k*k;
     46 }
     47 bool cmp(int x,int y){
     48     return bl[x]<bl[y];
     49 }
     50 void init(){
     51     E=0;
     52     memset(head,-1,sizeof(head));
     53 }
     54 void add(int x,int y,ll z){
     55     edge[E].nex=head[x];
     56     edge[E].to=y;
     57     edge[E].len=z;
     58     head[x]=E++;
     59     if (E&1)add(y,x,0);
     60 }
     61 bool bfs(){
     62     memset(d,oo,sizeof(d));
     63     d[0]=0;
     64     q.push(0);
     65     while (!q.empty()){
     66         int k=q.front();
     67         q.pop();
     68         for(int i=head[k];i!=-1;i=edge[i].nex)
     69             if ((edge[i].len)&&(d[edge[i].to]==oo)){
     70                 d[edge[i].to]=d[k]+1;
     71                 q.push(edge[i].to);
     72             }
     73     }
     74     return d[n+1]<oo;
     75 }
     76 ll dfs(int k,ll s){
     77     if (k>n)return s;
     78     for(int &i=work[k];i!=-1;i=edge[i].nex)
     79         if ((edge[i].len)&&(d[edge[i].to]==d[k]+1)){
     80             ll p=dfs(edge[i].to,min(s,edge[i].len));
     81             if (p){
     82                 edge[i].len-=p;
     83                 edge[i^1].len+=p;
     84                 return p;
     85             }
     86         }
     87     return 0;
     88 }
     89 void dinic(){
     90     while (bfs()){
     91         memcpy(work,head,sizeof(work));
     92         while (dfs(0,1e12));
     93     }
     94 }
     95 void dfs(int k){
     96     if (vis[k])return;
     97     vis[k]=1;
     98     for(int i=head[k];i!=-1;i=edge[i].nex)
     99         if (edge[i].len)dfs(edge[i].to);
    100 }
    101 void dfs(int l,int r,int x,int y){
    102     if (x==y){
    103         for(int i=l;i<=r;i++)ans[a[i]]=x;
    104         return;
    105     }
    106     int mid=(x+y>>1);
    107     init();
    108     for(int i=l;i<=r;i++){
    109         ll wx=sqr(w[a[i]]-mid),wy=sqr(w[a[i]]-mid-1);
    110         if (wx>wy){
    111             bl[a[i]]=1;
    112             add(0,i,wx-wy);
    113         }
    114         else{
    115             bl[a[i]]=0;
    116             add(i,n+1,wy-wx);
    117         }
    118     }
    119     for(int i=l;i<=r;i++)
    120         for(int j=l;j<=r;j++)
    121             if (lim[a[i]][a[j]])add(i,j,oo);
    122     dinic();
    123     memset(vis,0,sizeof(vis));
    124     dfs(0);
    125     for(int i=head[0];i!=-1;i=edge[i].nex)
    126         if (!vis[edge[i].to])bl[a[edge[i].to]]=0;
    127     for(int i=head[n+1];i!=-1;i=edge[i].nex)
    128         if (vis[edge[i].to])bl[a[edge[i].to]]=1;
    129     sort(a+l,a+r+1,cmp);
    130     for(int i=l;i<=r+1;i++){
    131         if ((bl[a[i]])||(i>r)){
    132             if (l<i)dfs(l,i-1,x,mid);
    133             if (i<=r)dfs(i,r,mid+1,y);
    134             return;
    135         }
    136     }
    137 }
    138 int main(){
    139     scanf("%d%d",&n,&m);
    140     for(int i=1;i<=n;i++)scanf("%llu",&c[i]);
    141     for(int i=1;i<=n;i++)scanf("%d",&w[i]);
    142     for(int i=1;i<=m;i++){
    143         scanf("%d",&x);
    144         add(c[x],x);
    145         vis[x]=1;
    146     }
    147     for(int i=1;i<=n;i++)
    148         if (!vis[i])query(c[i],i,0);
    149     memset(vis,0,sizeof(vis));
    150     memset(val,0,sizeof(val));
    151     for(int i=1;i<=m;i++){
    152         scanf("%d",&x);
    153         add(c[x],x);
    154         vis[x]=1;
    155     }
    156     for(int i=1;i<=n;i++)
    157         if (!vis[i])query(c[i],i,1);
    158     for(int i=1;i<=n;i++)a[i]=i;
    159     dfs(1,n,0,1e6);
    160     for(int i=1;i<=n;i++)sum+=sqr(ans[i]-w[i]);
    161     printf("%lld",sum);
    162 }
    View Code
  • 相关阅读:
    MySQL概述
    Seleniumselenium基础入门
    MySQL数据库的安装与使用
    元素定位_id
    Selenium浏览器的前进、后退、刷新
    元素定位_tag_name
    Selenium浏览器操作_窗口大小设置
    元素定位_name
    搭建maven服务器(repository)
    使用dos命令生成目录树
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/14929412.html
Copyright © 2011-2022 走看看