二分+树状数组/线段树(区间更新) HDOJ 4339 Query
题意:给两串字符串,操作1:替换其中一个字符串的某个位置的字符 操作2:查询从p开始相等的最长连续长度
分析:树状数组可以维护一个区间内公共长度(连续)的情况,查询时用二分查找最远的端点即可。还可以用线段树去做,线段树能处理的问题很多,这题只要往右区间合并就行了。
收获:1.线段树的区间合并又做一题(虽然我写的还没AC) 2. 树状数组写起来方便又奇效!
代码1(树状数组):
/************************************************
* Author :Running_Time
* Created Time :2015-8-26 9:46:09
* File Name :I.cpp
************************************************/ #include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std; #define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 1e6 + 10;
const int Q = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
char s1[N], s2[N];
int L;
struct BIT {
int c[N];
void init(void) {
memset (c, 0, sizeof (c));
}
void updata(int i, int x) {
while (i <= L) {
c[i] += x; i += (i & (-i));
}
}
int query(int i) {
int ret = 0;
while (i) {
ret += c[i]; i -= (i & (-i));
}
return ret;
}
int bsearch(int p, int l, int r) {
while (l <= r) {
int mid = (l + r) >> 1;
if (query (mid) - query (p-1) == mid - p + 1) l = mid + 1;
else r = mid - 1;
}
return l - p;
}
}bit; int main(void) {
int T, cas = 0; scanf ("%d", &T);
while (T--) {
scanf ("%s%s", s1 + 1, s2 + 1);
int q; scanf ("%d", &q);
int len1 = strlen (s1 + 1), len2 = strlen (s2 + 1);
L = min (len1, len2); bit.init ();
for (int i=1; i<=L; ++i) {
if (s1[i] == s2[i]) bit.updata (i, 1);
}
printf ("Case %d:\n", ++cas);
while (q--) {
int op; scanf ("%d", &op);
if (op == 1) {
int x, p; char c; scanf ("%d%d %c", &x, &p, &c);
++p;
if (p > L) continue;
bool same = (s1[p] == s2[p]);
if (x == 1) {
s1[p] = c;
if (same && s1[p] != s2[p]) bit.updata (p, -1);
else if (!same && s1[p] == s2[p]) bit.updata (p, 1);
}
else {
s2[p] = c;
if (same && s1[p] != s2[p]) bit.updata (p, -1);
else if (!same && s1[p] == s2[p]) bit.updata (p, 1);
}
}
else {
int p; scanf ("%d", &p);
++p;
if (p > L) {
puts ("0"); continue;
}
printf ("%d\n", bit.bsearch (p, p, L));
}
}
} return 0;
}
代码2(线段树):
/************************************************
* Author :Running_Time
* Created Time :2015-8-26 9:46:09
* File Name :I.cpp
************************************************/ #include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std; #define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 1e6 + 10;
const int Q = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
char s1[N], s2[N];
struct ST {
int sum[N<<2];
void push_up(int rt, int len) { //sum[rt<<1]表示从左子树线段左端点开始最长连续的公共的长度,如果全是公共的,
if (sum[rt<<1] == len - (len >> 1)) sum[rt] = sum[rt<<1] + sum[rt<<1|1]; //合并右子树的线段长度
else sum[rt] = sum[rt<<1];
}
void build(int l, int r, int rt) {
if (l == r) {
sum[rt] = s1[l] == s2[r] ? 1 : 0;
return ;
}
int mid = (l + r) >> 1;
build (lson); build (rson);
push_up (rt, r - l + 1);
}
void updata(int p, int c, int l, int r, int rt) {
if (l == r) {
sum[rt] = c; return ;
}
int mid = (l + r) >> 1;
if (p <= mid) updata (p, c, lson);
else updata (p, c, rson);
push_up (rt, r - l + 1);
}
int query(int p, int l, int r, int rt) {
if (l == r) return sum[rt];
int mid = (l + r) >> 1;
if (p <= mid) {
int ret = query (p, lson);
if (p + ret - 1 == mid) return ret + sum[rt<<1|1];
else return ret;
}
else return query (p, rson);
}
}st; int main(void) {
int T, cas = 0; scanf ("%d", &T);
while (T--) {
scanf ("%s%s", s1 + 1, s2 + 1);
int q; scanf ("%d", &q);
int len1 = strlen (s1 + 1), len2 = strlen (s2 + 1);
int mn = min (len1, len2);
st.build (1, mn, 1); printf ("Case %d:\n", ++cas);
while (q--) {
int op; scanf ("%d", &op);
if (op == 1) {
int x, p; char c; scanf ("%d%d %c", &x, &p, &c);
++p;
if (p > mn) continue; //特殊情况特判
if (x == 1) {
s1[p] = c;
}
else {
s2[p] = c;
}
st.updata (p, (s1[p] == s2[p]), 1, mn, 1);
}
else {
int p; scanf ("%d", &p);
++p;
if (p > mn) { //特殊情况特判
puts ("0"); continue;
}
printf ("%d\n", st.query (p, 1, mn, 1));
}
}
} return 0;
}
代码3(unAC):
/************************************************
* Author :Running_Time
* Created Time :2015-8-26 9:46:09
* File Name :I.cpp
************************************************/ #include <cstdio>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <list>
#include <map>
#include <set>
#include <bitset>
#include <cstdlib>
#include <ctime>
using namespace std; #define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
typedef long long ll;
const int N = 1e6 + 10;
const int Q = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
char s1[N], s2[N];
struct ST {
int sum[N<<2], lsum[N<<2], rsum[N<<2];
void push_up(int rt, int len) {
lsum[rt] = lsum[rt<<1];
rsum[rt] = rsum[rt<<1|1];
sum[rt] = max (sum[rt<<1], sum[rt<<1|1]);
if (lsum[rt] == len - (len >> 1)) lsum[rt] += lsum[rt<<1|1];
if (rsum[rt] == len >> 1) rsum[rt] += rsum[rt<<1];
sum[rt] = max (rsum[rt<<1] + lsum[rt<<1|1], max (sum[rt<<1], sum[rt<<1|1]));
}
void build(int l, int r, int rt) {
if (l == r) {
sum[rt] = lsum[rt] = rsum[rt] = s1[l] == s2[r] ? 1 : 0;
return ;
}
int mid = (l + r) >> 1;
build (lson); build (rson);
push_up (rt, r - l + 1);
}
void updata(int p, int c, int l, int r, int rt) {
if (l == r) {
sum[rt] = lsum[rt] = rsum[rt] = c; return ;
}
int mid = (l + r) >> 1;
if (p <= mid) updata (p, c, lson);
else updata (p, c, rson);
push_up (rt, r - l + 1);
}
int query(int p, int l, int r, int rt) {
if (l == r) return sum[rt];
int mid = (l + r) >> 1;
if (p <= mid) {
if (p + rsum[rt<<1] - 1 >= mid) return mid - p + 1 + query (p, rson);
else return query (p, lson);
}
else return query (p, lson);
}
}st; int main(void) {
int T, cas = 0; scanf ("%d", &T);
while (T--) {
scanf ("%s%s", s1 + 1, s2 + 1);
int q; scanf ("%d", &q);
int len1 = strlen (s1 + 1), len2 = strlen (s2 + 1);
int mn = min (len1, len2);
st.build (1, mn, 1); printf ("Case %d:\n", ++cas);
while (q--) {
int op; scanf ("%d", &op);
if (op == 1) {
int x, p; char c; scanf ("%d%d %c", &x, &p, &c);
if (p + 1 > mn) continue;
if (x == 1) {
s1[p+1] = c;
}
else {
s2[p+1] = c;
}
st.updata (p+1, (s1[p+1] == s2[p+1]), 1, mn, 1);
}
else {
int p; scanf ("%d", &p);
if (p + 1 > mn) {
puts ("0"); continue;
}
printf ("%d\n", st.query (p + 1, 1, mn, 1));
}
}
} return 0;
}
二分+树状数组/线段树(区间更新) HDOJ 4339 Query的更多相关文章
- hdu1394(枚举/树状数组/线段树单点更新&区间求和)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题意:给出一个循环数组,求其逆序对最少为多少: 思路:对于逆序对: 交换两个相邻数,逆序数 +1 ...
- 洛谷P2414 阿狸的打字机 [NOI2011] AC自动机+树状数组/线段树
正解:AC自动机+树状数组/线段树 解题报告: 传送门! 这道题,首先想到暴力思路还是不难的,首先看到y有那么多个,菜鸡如我还不怎么会可持久化之类的,那就直接排个序什么的然后按顺序做就好,这样听说有7 ...
- 树状数组 && 线段树应用 -- 求逆序数
参考:算法学习(二)——树状数组求逆序数 .线段树或树状数组求逆序数(附例题) 应用树状数组 || 线段树求逆序数是一种很巧妙的技巧,这个技巧的关键在于如何把原来单纯的求区间和操作转换为 求小于等于a ...
- Holedox Eating HDU - 4302 2012多校C 二分查找+树状数组/线段树优化
题意 一个长度$n<=1e5$的数轴,$m<=1e5$个操作 有两种一些操作 $0$ $x$ 在$x$放一个食物 $1$ 一个虫子去吃最近的食物,如果有两个食物一样近,不转变方向的去吃 ...
- hdu 1166:敌兵布阵(树状数组 / 线段树,入门练习题)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- [洛谷P1198/BZOJ1012][JSOI2008] 最大数 - 树状数组/线段树?
其实已经学了树状数组和线段树,然而懒得做题,所以至今没写多少博客 Description 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数 ...
- hdu 5147 Sequence II【树状数组/线段树】
Sequence IITime Limit: 5000/2500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem ...
- BZOJ.3110.[ZJOI2013]K大数查询(整体二分 树状数组/线段树)
题目链接 BZOJ 洛谷 整体二分求的是第K小(利用树状数组).求第K大可以转为求第\(n-K+1\)小,但是这样好像得求一个\(n\). 注意到所有数的绝对值\(\leq N\),将所有数的大小关系 ...
- hdu 1166 敌兵布阵——(区间和)树状数组/线段树
pid=1166">here:http://acm.hdu.edu.cn/showproblem.php?pid=1166 Input 第一行一个整数T.表示有T组数据. 每组数据第一 ...
随机推荐
- java实现从报文中获取投保单号
java实现从报文中获取投保单号 投保单号正则表达式: String regex = "<proposalNo>([0-9]+)</proposalNo>[\\s\\ ...
- 怎样免费设置QQ空间背景音乐
怎样免费设置QQ空间背景音乐 1.打开QQ空间,点击 2. 3. 4.这里它要求我们输入歌曲的在线路径,并且必须是MP3格式的,这就简单了,我们仅仅要去网上找在线的MP3音乐就能够了.可是如今非常多提 ...
- Centos 6.4 搭建LANMP一键安装版
lanmp一键安装包是wdlinux官网2010年开始推出的lamp,lnmp,lnamp(apache,nginx,php,mysql,zend,eAccelerator,pureftpd)应用环境 ...
- sharpdevelop 调整代码字体显示大小
SharpDevelop中使用ctrl+鼠标滚轮可以调整代码的字体显示大小
- bean的scope属性
1.singleton (默认属性) Spring将Bean放入Spring IOC容器的缓存池中,并将Bean引用返回给调用者,spring IOC继续对这些Bean进行后续的生命管理.Bean ...
- Webservice(CXF) 、 POI(excel)操作部署到weblogic上冲突解决
这几日把webservice和POI 操作部署到WebLogic上,问题重重,有各种冲突. 部署到tomcat上没有问题 版本: jdk:6 tomcat:6 weblogic:10.3.3 cxf: ...
- 设计模式-(18)命令模式 (swift版)
一,概念: 在软件系统中,“行为请求者”与“行为实现者”通常呈现一种“紧耦合”.但在某些场合,比如要对行为进行“记录.撤销/重做.事务”等处理,这种无法抵御变化的紧耦合是不合适的.在这种情况下,如何将 ...
- Lightoj 1018 - Brush (IV)
1018 - Brush (IV) PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB Muba ...
- UVA11324 The Largest Clique —— 强连通分量 + 缩点 + DP
题目链接:https://vjudge.net/problem/UVA-11324 题解: 题意:给出一张有向图,求一个结点数最大的结点集,使得任意两个结点u.v,要么u能到达v, 要么v能到达u(u ...
- POJ1733 Parity game —— 种类并查集
题目链接:http://poj.org/problem?id=1733 Parity game Time Limit: 1000MS Memory Limit: 65536K Total Subm ...