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
原文地址:https://www.cnblogs.com/Achenchen/p/9572666.html