线段树教做人系列(2)HDU 4867 XOR
题意:给你一个数组a,长度为。有两种操作。一种是改变数组的某个元素的值,一种是满足某种条件的数组b有多少种。条件是:b[i] <= a[i],并且b[1]^b[2]...^b[n] = k的数组有多少种。数组a的元素都小于1000.
思路:因为数很小,我们把数变成二进制数,然后拆分二进制数。比如1101可以拆成10xx,x可为0可为1,有点像数位dp的试填法。我们对每个a[i]存若干个前缀,记录前缀的长度,以及是这个前缀的二进制数有多少个。然后我们合并相邻的区间,直接暴力二重循环,然后合并。其实这个过程更像dp的过程,感觉只是用了线段树的划分成区间,然后合并的思想。
思路参考这两篇博客:https://blog.csdn.net/jtjy568805874/article/details/56488626, https://blog.csdn.net/qian99/article/details/38171951
代码:
#include <bits/stdc++.h>
#define pii pair<int, int>
#define lowbit(x) (x & (-x))
#define mk make_pair
#define ls(x) (x << 1)
#define rs(x) ((x << 1) | 1)
#define LL long long
using namespace std;
const LL mod = 1000000007;
const int maxn = 20010; int Log[2010], a[maxn];
struct node {
pii x;
LL tot;
bool operator < (const node& rhs) const {
return x < rhs.x;
}
}; vector<node> tr[maxn * 4], tmp; int get(int x, int y) {
tr[x].clear();
tr[x].push_back((node){mk(y, 10), 1});
for (int i = y; i; i -= lowbit(i)) {
tr[x].push_back((node){mk(i - lowbit(i), 10 - Log[lowbit(i)]), lowbit(i)});
}
} void pushup(int x, int l, int r) {
tmp.clear();
tr[x].clear();
for (int i = 0; i < tr[l].size(); i++) {
for (int j = 0; j < tr[r].size(); j++) {
node t1 = tr[l][i], t2 = tr[r][j];
int now = t1.x.first ^ t2.x.first, len = min(t1.x.second, t2.x.second);
now = ((now >> (10 - len)) << (10 - len));
tmp.push_back((node){mk(now, len), (t1.tot * t2.tot) % mod});
}
}
sort(tmp.begin(), tmp.end());
for (int i = 0, j; i < tmp.size(); i = j) {
node tmp1 = (node){tmp[i].x, 0};
for (j = i; j < tmp.size() && tmp[i].x == tmp[j].x; j++) {
tmp1.tot = (tmp1.tot + tmp[j].tot) % mod;
}
tr[x].push_back(tmp1);
}
} void build(int x, int l, int r) {
if(l == r) {
get(x, a[l]);
return;
}
int mid = (l + r) >> 1;
build(ls(x), l ,mid);
build(rs(x), mid + 1, r);
pushup(x, ls(x), rs(x));
} LL inv(int x) {
return x == 1 ? 1 : 1ll * inv(mod % x)*(mod - mod / x) % mod;
} void update(int x, int l, int r, int pos, int val) {
if(l == r) {
get(x, val);
return;
}
int mid = (l + r) >> 1;
if(pos <= mid) update(ls(x), l, mid, pos, val);
else update(rs(x), mid + 1, r, pos, val);
pushup(x, ls(x), rs(x));
} LL query(int x) {
LL ans = 0;
for (int i = 0; i < tr[1].size(); i++) {
node t = tr[1][i];
if((t.x.first ^ x) >> (10 - t.x.second)) continue;
ans = (ans + (t.tot * inv(1 << (10 - t.x.second))) % mod) % mod;
}
return ans;
}
int main() {
int n, m;
int x, y;
char s[10];
for (int i = 1; i <= 10; i++)
Log[1 << i] = i;
int T;
cin >> T;
while(T--) {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
build(1, 1, n);
while(m--) {
scanf("%s",s + 1);
if(s[1] == 'Q') {
scanf("%d", &x);
printf("%lld\n", query(x));
} else {
scanf("%d%d", &x, &y);
update(1, 1, n, x + 1, y);
}
}
}
}
线段树教做人系列(2)HDU 4867 XOR的更多相关文章
- 线段树教做人系列(3) HDU 4913
题意及思路看这篇博客就行了,讲得很详细. 下面是我自己的理解: 如果只有2,没有3的话,做法就很简单了,只需要对数组排个序,然后从小到大枚举最大的那个数.那么它对答案的贡献为(假设这个数排序后的位置是 ...
- Codeforces 719E (线段树教做人系列) 线段树维护矩阵
题面简洁明了,一看就懂 做了这个题之后,才知道怎么用线段树维护递推式.递推式的递推过程可以看作两个矩阵相乘,假设矩阵A是初始值矩阵,矩阵B是变换矩阵,求第n项相当于把矩阵B乘了n - 1次. 那么我们 ...
- 线段树教做人系列(1)HDU4967 Handling the Past
题意:给你n组操作,分别为压栈,出栈,询问栈顶元素.每一组操作有一个时间戳,每次询问栈顶的元素的操作询问的是在他之前出现的操作,而且时间戳小于它的情况.题目中不会出现栈为空而且出栈的情况. 例如: p ...
- Codeforces 1136E Nastya Hasn't Written a Legend (线段树教做人系列)
题意:有一个数组a和一个数组k,数组a一直保持一个性质:a[i + 1] >= a[i] + k[i].有两种操作:1,给某个元素加上x,但是加上之后要保持数组a的性质.比如a[i]加上x之后, ...
- 线段树(单点更新,区间查询) HDU 1754 I Hate It
题目链接 线段树的模板 #include<iostream> #include<cstdio> #include<cmath> #include<algori ...
- 线段树(区间合并)HDU - 1540
题意:输入n,m,给定n个相互连通的村庄,有m个操作,D x,表示破坏x村庄使其与相邻的两个村庄不相通,R 表示修复上一个被破坏的村庄,与相邻的两个村庄联通.Q x表示与x相连的村庄有多少个. 思路: ...
- (线段树 区间查询)The Water Problem -- hdu -- 5443 (2015 ACM/ICPC Asia Regional Changchun Online)
链接: http://acm.hdu.edu.cn/showproblem.php?pid=5443 The Water Problem Time Limit: 1500/1000 MS (Java/ ...
- (线段树)Just a Hook -- hdu -- 1689
链接: http://acm.hdu.edu.cn/showproblem.php?pid=1698 思路: 我的想法很简单,像上一题一样从后面向前面来算,前面已经覆盖的,后面自然不能再来计算了,具体 ...
- 线段树(区间修改、区间查询) HDU 1754 I Hate It
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
随机推荐
- android 取mac若干问题
问题一:Error:Error: The WIFI_SERVICE must be looked up on the Application context or memory will leak o ...
- asp.net上传文件大小限制
<system.webServer> <security> <requestFiltering> <requestLimits maxAllowedConte ...
- Vue中mixin的用法
在项目中我们经常会遇到多个组件调用同一个方法的问题,为了避免每次都在.vue文件中定义并调用,我们可采用vue的mixin的用法: 具体使用如下: 我们需要在main.js中引入mixins文件夹下的 ...
- ie-9 以下ajax无法跨域的问题。只要add:jQuery.support.cors=true;即可
if (!jQuery.support.cors && window.XDomainRequest) { var httpRegEx = /^https?:\/\//i; var ge ...
- (转)轻量级C语言实现的minixml解析库入门教程
svn上的minixml源码下载:svn co http://svn.msweet.org/mxml/tags/release-2.7/ 按照下载回来的源代码进行编译和安装.本教程只针对新手做一个引导 ...
- 2017.10.4北京清北综合强化班DAY4
财富(treasure) Time Limit:1000ms Memory Limit:128MB 题目描述 LYK有n个小伙伴.每个小伙伴有一个身高hi. 这个游戏是这样的,LYK生活的环境是以 ...
- ASP.NET MVC 缓存Outputcache (局部动态)
首先说一下需求: 比如我需要对网站首页做缓存,于是在首页对于的Action上贴上了Outputcache,接着问题就来了,首页上的有部分数据是不能做缓存的,比如个人信息,不然,每个人登陆都是看到第一个 ...
- [转] 如何用BSP树生成游戏地图
作者:Timothy Hely 当用对象随机填充某个区域如地下城中的房间时,你可能会遇到的问题是太过随机,导致分布疏密不均或混乱.在本教程中,我将告诉大家如何使用二进制空间划分法(游戏邦注:即Bina ...
- 12.Selenium+Python案例 -- 今日头条(获取科技栏目的所有新闻标题)
一:具体代码实现 # -*- coding: utf-8 -*-# @Time : 2018/7/26 16:33# @Author : Nancy# @Email : NancyWangDL@163 ...
- 判断唯一约束是否是唯一的Unique
//检查 唯一约束Name //检查 唯一约束Name int count = new BLL.Funcs().GetRecordCount(string.Format("Name={0}& ...