zoukankan      html  css  js  c++  java
  • Kattis

    题意:有一个长度为n的序列,让你把它分成k段,段内元素取or,段间取and,求能够得到的最大值。

    这个算法是我和xz场上yy出来的,然而时间不够了没写出来,而且时间复杂度是$O(nlogn+nlogA)$的比官方题解都要低...(但是常数大了点)

    设最大值为ans,我们假设S&ans=S,看看S能否用k条线段凑出来,则将原问题转化成了一个判定问题。从高到低一位一位地考虑,最多只需进行$O(logA)$次判定。

    如何进行判定呢?

    首先将原数组复制一倍接到后面,然后进行两次尺取。第一次求出每个左端点l所对应的能够覆盖S的最小的右端点r并把它作为一条线段放进数组里(能够覆盖S的意思是S的每一位上的1都可以在[l,r]区间里的某个元素中取到,可以用RMQ预处理区间or然后$O(1)$判断),第二次则对这些线段进行尺取,求出每条线段右边第一条和它不相交的线段,将每条线段与这样的线段连边,可以得到一棵树(或者森林,若为森林则将所有树和一个虚节点连边即可变成一棵树),只需要检查一下这棵树上是否有一个结点的l和与它距离为k的父亲结点的r的区间长度r-l+1是否小于n,从根节点dfs一遍即可。

    代码:(我写了两份,第一份怕爆栈所以手写了数组模拟栈,第二份是普通的dfs)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e6+10;
     5 int n,k,a[N],ST[N][20],Log[N],nl,hd[N],ne,q[N],tp;
     6 void build() {
     7     for(int i=1; i<=2*n; ++i)ST[i][0]=a[i];
     8     for(int k=1; k<=Log[2*n]; ++k)
     9         for(int i=1; i+(1<<k)-1<=2*n; ++i)
    10             ST[i][k]=ST[i][k-1]|ST[i+(1<<(k-1))][k-1];
    11 }
    12 int qry(int L,int R) {
    13     int k=Log[R-L+1];
    14     return ST[L][k]|ST[R-(1<<k)+1][k];
    15 }
    16 struct D {int l,r;} line[N];
    17 struct E {int v,nxt;} e[N];
    18 struct ND {int u,dep;} sta[N];
    19 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
    20 bool dfs() {
    21     sta[tp=0]= {nl,0};
    22     while(~tp) {
    23         int u=sta[tp].u,dep=sta[tp--].dep;
    24         q[dep]=u;
    25         if(dep>=k&&line[q[dep-k+1]].r-line[u].l+1<=n)return 1;
    26         for(int i=hd[u]; ~i; i=e[i].nxt)sta[++tp]= {e[i].v,dep+1};
    27     }
    28     return 0;
    29 }
    30 bool ok(int S) {
    31     nl=0;
    32     for(int i=1,j=1; i<=2*n; ++i) {
    33         if(j<i)j=i;
    34         for(; j<=2*n&&(qry(i,j)&S)!=S; ++j);
    35         if(j<=2*n)line[nl++]= {i,j};
    36     }
    37     for(int i=0; i<=nl; ++i)hd[i]=-1;
    38     ne=0;
    39     for(int i=0,j=0; i<nl; ++i) {
    40         for(; j<nl&&line[j].l<=line[i].r; ++j);
    41         addedge(j,i);
    42     }
    43     return dfs();
    44 }
    45 int solve() {
    46     int ret=0;
    47     for(int i=30; i>=0; --i)if(ok(ret|(1<<i)))ret|=1<<i;
    48     return ret;
    49 }
    50 int main() {
    51     Log[0]=-1;
    52     for(int i=1; i<N; ++i)Log[i]=Log[i>>1]+1;
    53     scanf("%d%d",&n,&k);
    54     for(int i=1; i<=n; ++i)scanf("%d",&a[i]);
    55     for(int i=1; i<=n; ++i)a[i+n]=a[i];
    56     build();
    57     printf("%d
    ",solve());
    58     return 0;
    59 }
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 const int N=1e6+10;
     5 int n,k,a[N],ST[N][20],Log[N],nl,hd[N],ne,q[N];
     6 void build() {
     7     for(int i=1; i<=2*n; ++i)ST[i][0]=a[i];
     8     for(int k=1; k<=Log[2*n]; ++k)
     9         for(int i=1; i+(1<<k)-1<=2*n; ++i)
    10             ST[i][k]=ST[i][k-1]|ST[i+(1<<(k-1))][k-1];
    11 }
    12 int qry(int L,int R) {
    13     int k=Log[R-L+1];
    14     return ST[L][k]|ST[R-(1<<k)+1][k];
    15 }
    16 struct D {int l,r;} line[N];
    17 struct E {int v,nxt;} e[N];
    18 void addedge(int u,int v) {e[ne]= {v,hd[u]},hd[u]=ne++;}
    19 bool dfs(int u,int dep) {
    20     q[dep]=u;
    21     if(dep>=k&&line[q[dep-k+1]].r-line[u].l+1<=n)return 1;
    22     for(int i=hd[u]; ~i; i=e[i].nxt)if(dfs(e[i].v,dep+1))return 1;
    23     return 0;
    24 }
    25 bool ok(int S) {
    26     nl=0;
    27     for(int i=1,j=1; i<=2*n; ++i) {
    28         if(j<i)j=i;
    29         for(; j<=2*n&&(qry(i,j)&S)!=S; ++j);
    30         if(j<=2*n)line[nl++]= {i,j};
    31     }
    32     for(int i=0; i<=nl; ++i)hd[i]=-1;
    33     ne=0;
    34     for(int i=0,j=0; i<nl; ++i) {
    35         for(; j<nl&&line[j].l<=line[i].r; ++j);
    36         addedge(j,i);
    37     }
    38     return dfs(nl,0);
    39 }
    40 int solve() {
    41     int ret=0;
    42     for(int i=30; i>=0; --i)if(ok(ret|(1<<i)))ret|=1<<i;
    43     return ret;
    44 }
    45 int main() {
    46     Log[0]=-1;
    47     for(int i=1; i<N; ++i)Log[i]=Log[i>>1]+1;
    48     scanf("%d%d",&n,&k);
    49     for(int i=1; i<=n; ++i)scanf("%d",&a[i]);
    50     for(int i=1; i<=n; ++i)a[i+n]=a[i];
    51     build();
    52     printf("%d
    ",solve());
    53     return 0;
    54 }
  • 相关阅读:
    static,匿名对象
    构造方法
    面向对象
    数组拷贝,可变参数,foreach
    毕业设计 之 七 参考文献综述
    毕业设计 之 六 网站搭建学习笔记
    毕业设计 之 五 PHP语法学习笔记
    毕业设计 之 四 英文资料翻译
    毕业设计 之 三 mooodle及bigbluebutton使用笔记(未完成)
    毕业设计 之 二 PHP集成环境(Dreamweaver)使用
  • 原文地址:https://www.cnblogs.com/asdfsag/p/11517805.html
Copyright © 2011-2022 走看看