• NOIp2018集训test-9-1(am)


    1、最大值

    可以用FWT水过去,李巨写了FWT结果中途爆int了炸了几十分好像。

    我乱搞了一下把除了大数据有or的搞出来然后90,还是蛮划算的。我yy的做法:

    1、xor 字典树上贪心, 一开始我打了线性基,被自己蠢哭了。

    &和|

    用sum[i]表示i中二进制位为1的位置都是1的且不是i的数是否存在。我乱搞从大到小地把一个一个去掉处理的,FWT也可以处理这个,复杂度是一样的。

    2、&

      答案一定是a中的某个数,枚举a中的每个数a[i]看sum[a[i]]是否存在即可。

    3、|

      枚举a中每个数,从高位到低位贪心看它能|出来的最大数。用一个类似前缀和思想的限制,具体说,到某一位如果a[i]是0,看目前的限制|这一位的1的sum存不存在,存在就把目前的限制|这一位的1。

      1 //Achen
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdlib>
      6 #include<vector>
      7 #include<cstdio>
      8 #include<queue>
      9 #include<cmath>
     10 #include<set>
     11 #include<map>
     12 #define Formylove return 0
     13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
     14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
     15 const int N=1e5+7;
     16 typedef long long LL;
     17 typedef double db;
     18 using namespace std;
     19 int T,n,c,a[N],mxx,b[30],sum[1048579],cnt[1048579];
     20 
     21 template<typename T>void read(T &x)  {
     22     char ch=getchar(); x=0; T f=1;
     23     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
     24     if(ch=='-') f=-1,ch=getchar();
     25     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
     26 }
     27 
     28 int rt,ch[N*25][2],tot;
     29 void insert(int v) {
     30     int x=rt;
     31     For(i,0,20) {
     32         int c=((v&(1<<i))!=0);
     33         if(!ch[x][c]) {
     34             ch[x][c]=++tot;
     35             ch[tot][0]=ch[tot][1]=0;
     36         }
     37         x=ch[x][c];
     38     }
     39 }
     40 
     41 int qry(int v) {
     42     int x=rt,rs=0;
     43     For(i,0,20) {
     44         if(v&(1<<i)) {
     45             if(ch[x][0]) rs+=(1<<i),x=ch[x][0];
     46             else x=ch[x][1];
     47         }
     48         else {
     49             if(ch[x][1]) rs+=(1<<i),x=ch[x][1];
     50             else x=ch[x][0];
     51         }    
     52     }
     53     return rs;
     54 }
     55 
     56 #define ANS
     57 int main() {
     58 #ifdef ANS
     59     freopen("maximum.in","r",stdin);
     60     freopen("maximum.out","w",stdout);
     61 #endif
     62     read(T);
     63     while(T--) {
     64         read(n); read(c);
     65         For(i,1,n) { read(a[i]); if(a[i]>mxx) mxx=a[i]; } 
     66         if(n<=1000) {
     67             int ans=0;
     68             For(i,1,n) For(j,i+1,n) {
     69                 if(c==1) ans=max(ans,(a[i]&a[j]));
     70                 else if(c==2) ans=max(ans,(a[i]^a[j]));
     71                 else ans=max(ans,(a[i]|a[j]));
     72             }
     73             printf("%d
    ",ans);
     74         }
     75         else if(mxx<=1024) {
     76             int ans=0;
     77             For(i,0,1024) cnt[i]=0;
     78             For(i,1,n) cnt[a[i]]++;
     79             For(i,0,1024) if(cnt[i]) {
     80                 if(cnt[i]>=2) {
     81                     if(c==1) ans=max(ans,(i&i));
     82                     else if(c==2) ans=max(ans,(i^i));
     83                     else ans=max(ans,(i|i));
     84                 }
     85                 For(j,i+1,1024) if(cnt[j]) {
     86                     if(c==1) ans=max(ans,(i&j));
     87                     else if(c==2) ans=max(ans,(i^j));
     88                     else ans=max(ans,(i|j));
     89                 }
     90             }
     91             printf("%d
    ",ans);
     92         }
     93         else {
     94             if(c!=2) {
     95                 memset(cnt,0,sizeof(cnt));
     96                 memset(sum,0,sizeof(sum));
     97                 int up=mxx;
     98                  For(i,1,n) {
     99                      cnt[a[i]]++;
    100                     For(j,0,20) if(a[i]&(1<<j)) 
    101                         sum[a[i]^(1<<j)]=1;
    102                 }
    103                 Rep(i,up,0) if(sum[i]) {
    104                     For(j,0,20) if(i&(1<<j)) 
    105                         sum[i^(1<<j)]=1;
    106                 }
    107             } 
    108             if(c==1) { //&
    109                 int ans=0;
    110                  For(i,1,n) if(cnt[a[i]]>=1||sum[a[i]]) {
    111                     if(a[i]>ans) ans=a[i]; 
    112                 }
    113                 printf("%d
    ",ans);
    114             } 
    115             else if(c==2) { //^
    116                 int rs=0;
    117                 ch[rt][0]=ch[rt][1]=0;
    118                 For(i,1,n) insert(a[i]);
    119                 For(i,1,n) rs=max(rs,qry(a[i]));
    120                 printf("%d
    ",rs);
    121             }
    122             else { // |
    123                 int ans=0;
    124                 For(i,1,n) {
    125                     int pr=0;
    126                     Rep(j,20,0) if(!(i&(1<<j))) {
    127                         if(sum[pr|(1<<j)]||cnt[pr|(1<<j)]) pr|=(1<<j);
    128                     }
    129                     ans=max(ans,(a[i]|pr));
    130                 }
    131                 printf("%d
    ",ans);
    132             }
    133         }
    134     }
    135     Formylove;
    136 }
    View Code

    2、独木桥

    之前考过的题啊。二分套二分。

    老张给的大数据有毒,大数据给错了,害我调了1个小时。。。

     1 //Achen
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<vector>
     7 #include<cstdio>
     8 #include<queue>
     9 #include<cmath>
    10 #include<set>
    11 #include<map>
    12 #define Formylove return 0
    13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
    14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
    15 const int N=2e5+7;
    16 typedef long long LL;
    17 typedef double db;
    18 using namespace std;
    19 int n,m,d;
    20 int px[N],rak[N],p[N],lp[N],rp[N],mi,mx;
    21 
    22 template<typename T>void read(T &x)  {
    23     char ch=getchar(); x=0; T f=1;
    24     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    25     if(ch=='-') f=-1,ch=getchar();
    26     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    27 }
    28 
    29 int find(int ti,int pos) {
    30     int rs=0;
    31     int l=1,r=lp[0],tp=-1;
    32     while(l<=r) {
    33         int mid=((l+r)>>1);
    34         if(lp[mid]-ti<=pos) tp=mid,l=mid+1; 
    35         else r=mid-1;
    36     }
    37     if(tp!=-1) rs+=tp;
    38     l=1,r=rp[0],tp=-1;
    39     while(l<=r) {
    40         int mid=((l+r)>>1);
    41         if(rp[mid]+ti<=pos) tp=mid,l=mid+1;
    42         else r=mid-1;
    43     }
    44     if(tp!=-1) rs+=tp;
    45     return rs;
    46 }
    47 
    48 #define ANS
    49 int main() {
    50 #ifdef ANS
    51     freopen("bridge.in","r",stdin);
    52     freopen("bridge.out","w",stdout);
    53 #endif
    54     read(n);
    55     For(i,1,n) read(p[i]),px[i]=p[i];
    56     sort(px+1,px+n+1);
    57     For(i,1,n) rak[i]=lower_bound(px+1,px+n+1,p[i])-px; 
    58     For(i,1,n) {
    59         read(d);
    60         if(d) rp[++rp[0]]=p[i];
    61         else lp[++lp[0]]=p[i];
    62         mi=min(mi,p[i]); mx=max(mx,p[i]);
    63     }
    64     sort(rp+1,rp+rp[0]+1);
    65     sort(lp+1,lp+lp[0]+1);
    66     read(m);
    67     For(i,1,m) {
    68         int ti,k;
    69         read(k); k++; read(ti);
    70         k=rak[k];
    71         int l=mi-ti,r=mx+ti,rs=-1;
    72         while(l<=r) {
    73             int mid=(((LL)l+r)/2);
    74             if(find(ti,mid)>=k) rs=mid,r=mid-1;
    75             else l=mid+1;
    76         }
    77         printf("%d
    ",rs);
    78     }
    79     Formylove;
    80 }
    81 /*
    82 5
    83 8 7 8 1 4 
    84 0 1 1 0 1 
    85 5
    86 5 11
    87 */
    View Code

    3、分组

    把s从小到大排序,一个个考虑放进组中,这样可以保证新建组的时候放入的一定是组内最小数,结束一个组的时候放入的一定是组内最大数。

    f[i][j][c]表示前i个数都分进了组,现在还有j个组没有结束,目前的代价是c的方案数。这样就可以过$sum s_i < 1000$的点了。

    算代价的时候是分别在最小的地方-s[i]和在最大的地方+s[i],显然代价单调不减,也就是虽然某个地方可能代价-s[i]但是后面一定会把这个代价加到非负。所以c一维最大只会到k。

    虽然最大只会到k,但是最小可以小到非常小,所以这种算代价的方式不太优秀。利用差分的思想,$s_i-s_j=sum_{k=j}^{k<i}s_{k+1}-s_k$,这样就可以使代价始终为正,把第三维压到k了。

     1 //Achen
     2 #include<algorithm>
     3 #include<iostream>
     4 #include<cstring>
     5 #include<cstdlib>
     6 #include<vector>
     7 #include<cstdio>
     8 #include<queue>
     9 #include<cmath>
    10 #include<set>
    11 #include<map>
    12 #define Formylove return 0
    13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
    14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
    15 const int p=1e9+7;
    16 typedef long long LL;
    17 typedef double db;
    18 using namespace std;
    19 int n,k,s[205];
    20 LL f[2][205][1005],cf[205];
    21 
    22 template<typename T>void read(T &x)  {
    23     char ch=getchar(); x=0; T f=1;
    24     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
    25     if(ch=='-') f=-1,ch=getchar();
    26     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
    27 }
    28 
    29 #define ANS
    30 int main() {
    31 #ifdef ANS
    32     freopen("group.in","r",stdin);
    33     freopen("group.out","w",stdout);
    34 #endif
    35     read(n); read(k);
    36     For(i,1,n) read(s[i]);
    37     sort(s+1,s+n+1);
    38     For(i,1,n) cf[i]=s[i+1]-s[i];
    39     int o=0;
    40     f[o][0][0]=1;
    41     For(i,0,n-1) {
    42         o^=1;
    43         memset(f[o],0,sizeof(f[o]));
    44         For(j,0,i) For(c,0,k) if(f[o^1][j][c]) {
    45             if(c+cf[i]*j<=k) {
    46                 (f[o][j][c+cf[i]*j]+=f[o^1][j][c]*(j+1)%p)%=p;
    47                 if(j) (f[o][j-1][c+cf[i]*j]+=(f[o^1][j][c]*j%p))%=p;
    48                 (f[o][j+1][c+cf[i]*j]+=f[o^1][j][c])%=p;
    49             }
    50         }
    51     }
    52     LL ans=0;
    53     For(i,0,k) 
    54         (ans+=f[o][0][i])%=p;
    55     printf("%lld
    ",ans);
    56     Formylove;
    57 }
    View Code
  • 相关阅读:
    PouchContainer Goroutine Leak 检测实践
    CDN全站加速助力企业云上升级
    互联网架构如何促进数字化营销
    设计模式之模板方法
    设计模式之外观模式
    设计模式之适配器模式
    分布式理论(一)CAP 理论
    边缘计算基本概念
    MQTT实战之MQTT入门
    高性能NIO通信框架之Netty架构总结(1)
  • 原文地址:https://www.cnblogs.com/Achenchen/p/9572666.html
Copyright © 2020-2023  润新知