HDU-4737-A Bit Fun-TwoPointer

来源:互联网 发布:单片机怎么打开 编辑:程序博客网 时间:2024/05/14 21:48

题目链接

题意:定义
fi,j=a[i]|a[i+1]|.....|a[j]

问有多少对i ,j满足f(i,j)小于m

思路1:第一种思路是暴力加剪枝(竟然过了),由于当i不变的时候,j增加的时候,f(i,j) 是递增的。所以可以直接退出

#include<bits/stdc++.h>#define maxn 111111using namespace std;int a[maxn];int main(){    int t;    int n,k;    int kase=0;    scanf("%d",&t);    while(t--) {        scanf("%d%d",&n,&k);        for(int i=1;i<=n;i++) {            scanf("%d",&a[i]);        }        int ans=0;        for(int i=1;i<=n;i++) {            int tmp=0;            for(int j=i;j<=n;j++) {                tmp|=a[j];                if(tmp<k) ans++;                else break;///因为这个是递增的所以可以直接退出                           ///这个剪纸很关键            }        }        printf("Case #%d: %d\n",++kase,ans);    }    return 0;}

思路2:用TwoPointer来维护,将每个数都转化成二进制,然后用c[i]来表示当前和中第i个二进制位有多少个1,返回和时,只要c[i] 大于0,就可以累加。

#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<iostream>#define maxn 111111using namespace std;int c[33];int a[maxn];int add(int x,int v) {    int ans=0;    for(int i=0;i<31;i++) {        if(x&(1 << i)) {            c[i]+=v;        }        if(c[i]) ans+=(1 << i);    }    return ans;}int main(){    int t;    int n,k;    int kase=0;    scanf("%d",&t);    while(t--) {        memset(c,0,sizeof c);        scanf("%d%d",&n,&k);        for(int i=1;i<=n;i++) {            scanf("%d",&a[i]);        }        int l=1,r=1;        int tot=0;        while(r<=n) {            int tmp=add(a[r++],1);            while(tmp>=k) {                tmp=add(a[l++],-1);            }            tot+=r-l;        }        printf("Case #%d: %d\n",++kase,tot);    }    return 0;}
0 0
原创粉丝点击