1674 区间的价值 V2(分治)
Posted happy_code
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1674 区间的价值 V2(分治)相关的知识,希望对你有一定的参考价值。
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
lyk拥有一个区间。
它规定一个区间的价值为这个区间中所有数and起来的值与这个区间所有数or起来的值的乘积。
例如3个数2,3,6。它们and起来的值为2,or起来的值为7,这个区间对答案的贡献为2*7=14。
现在lyk有一个n个数的序列,它想知道所有n*(n+1)/2个区间的贡献的和对1000000007取模后的结果是多少。
例如当这个序列为{3,4,5}时,那么区间[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]的贡献分别为9,0,0,16,20,25。
Input
第一行一个数n(1<=n<=100000)。 接下来一行n个数ai,表示这n个数(0<=ai<=10^9)。
Output
一行表示答案。
Input示例
3
3 4 5
Output示例
70
//想不到啊,还以为能找贡献水过呢。一种解法是分治,一段区间内,最多有 loga 种不同的 与,或 的值,将区间分半,对后半段统计与或值的个数,再对前半段扫一遍,累计答案即可,时间复杂度,n*lgn*lga
1 # include <cstdio> 2 # include <cstring> 3 # include <cstdlib> 4 # include <iostream> 5 # include <vector> 6 # include <queue> 7 # include <stack> 8 # include <map> 9 # include <bitset> 10 # include <sstream> 11 # include <set> 12 # include <cmath> 13 # include <algorithm> 14 using namespace std; 15 # define LL long long 16 # define pr pair 17 # define mkp make_pair 18 # define lowbit(x) ((x)&(-x)) 19 # define PI acos(-1.0) 20 # define INF 0x3f3f3f3f3f3f3f3f 21 # define eps 1e-8 22 # define MOD 1000000007 23 24 inline int scan() { 25 int x=0,f=1; char ch=getchar(); 26 while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘) f=-1; ch=getchar();} 27 while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘; ch=getchar();} 28 return x*f; 29 } 30 inline void Out(int a) { 31 if(a<0) {putchar(‘-‘); a=-a;} 32 if(a>=10) Out(a/10); 33 putchar(a%10+‘0‘); 34 } 35 # define MX 100005 36 /**************************/ 37 38 int n; 39 LL ans; 40 int num[MX]; 41 int AND[MX]; 42 int OR[MX]; 43 int tot[MX]; 44 45 void dfs(int l,int r) 46 { 47 if (l==r) 48 { 49 ans = (ans+(LL)num[l]*num[r]%MOD)%MOD; 50 return; 51 } 52 int mid = (l+r+1)>>1; 53 int pos = mid; 54 tot[pos]=0; AND[pos]=OR[pos]=num[pos]; 55 for (int i=mid;i<=r;i++) 56 { 57 if ( (num[i]&AND[pos]) != AND[pos] || (num[i]|OR[pos]) != OR[pos] ) 58 { 59 pos++; 60 AND[pos] = (num[i]&AND[pos-1]); 61 OR[pos] = (num[i]|OR[pos-1]); 62 tot[pos]=1; 63 } 64 else tot[pos]++; 65 } 66 int tpA = num[mid-1]; 67 int tpO = num[mid-1]; 68 for (int i=mid-1;i>=l;i--) 69 { 70 tpA&=num[i], tpO|=num[i]; 71 for (int j=mid;j<=pos;j++) 72 ans = (ans + ((LL)(tpA&AND[j])*(tpO|OR[j])%MOD) *tot[j]%MOD)%MOD; 73 } 74 dfs(mid,r); 75 dfs(l,mid-1); 76 } 77 78 int main() 79 { 80 scanf("%d",&n); 81 for (int i=1;i<=n;i++) 82 num[i]=scan(); 83 ans = 0; 84 dfs(1,n); 85 printf("%I64d\n",ans); 86 return 0; 87 }
以上是关于1674 区间的价值 V2(分治)的主要内容,如果未能解决你的问题,请参考以下文章