G - WiFi Password Gym - 101608G (异或思维题+曲尺)

题目链接:https://cn.vjudge.net/contest/285962#problem/G

题目大意:给你n和m,n代表有n个数,然后让你找出一个最长的区间,使得这个区间内的所有的数的‘’或‘’都小于等于m。

具体思路:曲尺,两个指针来回弄就行,具体的细节在代码里面,(以前做过的题现在竟然做不出来了,,我)

AC代码:

 1 #include<iostream>
 2 #include<stack>
 3 #include<stdio.h>
 4 #include<cmath>
 5 #include<algorithm>
 6 using namespace std;
 7 # define ll long long
 8 const int maxn = 3e6+100;
 9 ll a[maxn];
10 int main(){
11 freopen("wifi.in","r",stdin);
12 int T;
13 scanf("%d",&T);
14 while(T--){
15 ll n,m,tmp=0,tot=0,flag=0,ans=0,l,r;
16 scanf("%lld %lld",&n,&m);
17 for(ll i=1;i<=n;i++){
18 scanf("%lld",&a[i]);
19 ans=max(ans,tot);
20 if(a[i]<=m&&!flag){
21 l=i;
22 r=i;
23 tot=1;
24 tmp=a[i];
25 ans=max(ans,tot);
26 flag=1;
27 }
28 else if(flag){
29 ans=max(ans,tot);
30 if((tmp|a[i])<=m){
31 r++;
32 tmp|=a[i];
33 tot++;//计数的时候是按照合法的来记的,不能通过r-l+1来判断
34 ans=max(ans,tot);
35 continue;
36 }
37 ans=max(ans,tot);
38 if(a[i]>m){
39 tot=0;
40 flag=0;
41 tmp=0;
42 continue;
43 }
44 ans=max(ans,tot);
45 tmp=0;//注意这里的tmp直接归零就可以了。
46 ll pos=l;
47 r++;//注意先r++.
48 for(ll j=r;j>=pos;j--){
49 if((tmp|a[j])<=m){
50 tmp|=a[j];
51 l=j;
52 }
53 else break;
54 }
55 tot=r-l+1;// 合法块的大小重新赋值。
56 ans=max(ans,tot);
57 }
58 }
59 printf("%lld\n",ans);
60 }
61 return 0;
62 }

 

posted @ 2019-03-06 20:17  Let_Life_Stop  阅读(293)  评论(0编辑  收藏  举报