[暴力 乱搞] 51Nod 1674 算法马拉松19 A 区间的价值 V2

来源:互联网 发布:万网域名转入 编辑:程序博客网 时间:2024/05/16 15:13

因为每个点向前and 向前or 的后缀值是O(32) 

所以可以暴力分段求和 32n

类似的还有后缀gcd 是O(logV)的


#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;inline char nc(){  static char buf[100000],*p1=buf,*p2=buf;  if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }  return *p1++;}inline void read(int &x){  char c=nc(),b=1;  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()) x*=b;}const ll P=1000000007;const int N=100005;struct abcd{  int l,r,val;  abcd(int l=0,int r=0,int val=0):l(l),r(r),val(val) { }}And[35],Or[35];int tota,toto;int n,a[N];ll ans;int main(){  int pnt=0;  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  read(n); for (int i=1;i<=n;i++) read(a[i]);  for (int i=1;i<=n;i++){        for (int j=1;j<=tota;j++) And[j].val&=a[i];    And[++tota]=abcd(i,i,a[i]);    pnt=0;    for (int j=1;j<=tota;j++){      int l=And[j].l;      while (j+1<=tota && And[j+1].val==And[j].val) j++;      And[++pnt]=abcd(l,And[j].r,And[j].val);    }    tota=pnt;    for (int j=1;j<=toto;j++) Or[j].val|=a[i];    Or[++toto]=abcd(i,i,a[i]);    pnt=0;    for (int j=1;j<=toto;j++){      int l=Or[j].l;      while (j+1<=toto && Or[j+1].val==Or[j].val) j++;      Or[++pnt]=abcd(l,Or[j].r,Or[j].val);    }    toto=pnt;    int pnt1=1,pnt2=1;    for (int j=1;j<=i;){      while (j>And[pnt1].r) pnt1++;      while (j>Or[pnt2].r) pnt2++;      int last=min(And[pnt1].r,Or[pnt2].r);      ans+=(ll)And[pnt1].val*Or[pnt2].val%P*(last-j+1)%P;      ans%=P;      j=last+1;    }  }  printf("%lld\n",ans);  return 0;}


0 0