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 }