hdu - 4339 - Query - 树状数组||线段树
2012-08-20 22:41
375 查看
用树状数组和二分寻找连续的1.http://acm.hdu.edu.cn/showproblem.php?pid=4339
做题过程:
开始做的时候发现自己以前做过。索性做吧。神奇的是我发现我以前用树状数组和线段是各A了一遍。真是勤奋的孩子。
我对这题的二分很是反感,记得以前做的时候就二分了很久来着,而且只是二分不会。。。。。。
对于线段树的作法我已经淡忘了,只记得树状数组的。明天来把线段树的再一写。
今天我才意识到,单点更新这东西是更新到底层,复杂度很高的,没有什么优越性。
贴了以前的代码,因为以前的注释多。仍是不懂l,r,p有什么不同。正确的写着倒是很自然,但是不明白错的为什么错了。。。
做题过程:
开始做的时候发现自己以前做过。索性做吧。神奇的是我发现我以前用树状数组和线段是各A了一遍。真是勤奋的孩子。
我对这题的二分很是反感,记得以前做的时候就二分了很久来着,而且只是二分不会。。。。。。
对于线段树的作法我已经淡忘了,只记得树状数组的。明天来把线段树的再一写。
今天我才意识到,单点更新这东西是更新到底层,复杂度很高的,没有什么优越性。
/* Pro: 0 Sol: date: */ #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <set> #include <vector> using namespace std; char str[2][1000009],d[10]; int Q,t,op,a,b,len,c[1000009]; void modify(int pos, int val){ while(pos <= len){ c[pos] += val; pos += (pos & -pos); } } int getsum(int pos){ int sum = 0; while(pos){ sum += c[pos]; pos -= (pos & -pos); }return sum; } int bin(int low, int high){ int mid; int sum = getsum(low - 1),index = low; int ans = -1; while(low <= high){ mid = (low + high) >> 1; if(getsum(mid) - sum == mid - index + 1){ low = mid + 1; ans = max(ans,mid - index + 1); } else high = mid - 1; } return ans; } int main(){ scanf("%d",&t); for(int ca = 1; ca <= t; ca ++){ printf("Case %d:\n",ca); memset(str[0],0,strlen(str[0])); memset(str[1],0,strlen(str[1])); scanf("%s%s",str[0],str[1]); int len1 = strlen(str[0]); int len2 = strlen(str[1]); len = min(len1,len2); // memset(c,0,sizeof(c)); for(int i = 0; i < len; i ++){ if(str[0][i] == str[1][i]) modify(i + 1, 1); } scanf("%d",&Q); for(int i = 0; i < Q; i ++){ scanf("%d",&op); if(op == 2){ scanf("%d",&a); int tmp = bin(a + 1,len); if(tmp == -1) puts("0"); else printf("%d\n",tmp);//a + 1后面有多少个连续的1 }else{ scanf("%d%d%s",&a,&b,d); a --; int fk = (str[0][b] == str[1][b]); str[a][b] = d[0]; int fg = (str[a][b] == str[!a][b]); if(fk == 1 && fg == 0){//改前一样,改后不一样 modify(b + 1, -1); }else if(fk == 0 && fg == 1){//改前不一样,改后一样 modify(b + 1 ,1); } } } } return 0; }
贴了以前的代码,因为以前的注释多。仍是不懂l,r,p有什么不同。正确的写着倒是很自然,但是不明白错的为什么错了。。。
//思路: 单点更新,区间查询。 //线段树每个节点记录该区间从左向右最后一个相同的位置,若左边第一个就不相同,则记为-1 //这道题目的难点就是在于区间的合并的时候 #include <iostream> #include <cstring> #include <cstdio> #define lson l,m, rt << 1 #define rson m+ 1, r, rt << 1 | 1 #define maxn 1000100 #define havem int m = (l + r ) >> 1 using namespace std; int d[maxn << 2],Max; char s1[maxn],s2[maxn]; void push_up(int rt , int m){ if(d[rt << 1] == m){ d[rt] = max(d[rt << 1] , d[rt << 1 | 1]); }else d[rt] = d[rt << 1]; } void build(int l , int r, int rt){ if(l == r){ if(s1[l] == s2[r]) d[rt] = l; else d[rt] = -1; return ; } int m = (l + r) >> 1; build(lson); build(rson); push_up(rt,m); } //单点更新 void update(int id, int p, char cc, int l , int r, int rt){ if(l == r){ // cout << p << l << r << endl; if(id == 1) s1[p] = cc;//修改,这里如果是l也错了。难道说递归到底层l,r,p还不一样?好像是一样的啊。。。无语了。。。。 else s2[p] = cc; if(s1[l] == s2[r]) d[rt] = l; //这里一定要是l和r,如果是p,就wa了。why? else d[rt] = -1; return ; //永远不要忘记return } havem; if(p <= m) update(id,p,cc,lson); else update(id,p,cc,rson); push_up(rt,m); } //区间询问 int query(int L, int R, int l , int r, int rt){ if(L == l && R == r) return d[rt]; int m = (l + r) >> 1 , ret1= -1, ret2 = -1; if(R <= m) return query(L,R,lson); if(L > m) return query(L,R,rson); //执行到这里就是要查询的区间[L,R]覆盖[l,r]的中点了,这个时候需要注意了。 ret1 = query(L,m,lson); if(ret1 == m) { ret2 = query(m + 1, R, rson); return max(ret1,ret2); } else return ret1; } int main(){ int ca,Q,id,p,Max,cas = 1; char cc[4]; scanf("%d",&ca); while(ca --){ scanf("%s%s",s1,s2); scanf("%d",&Q); int len1 =strlen(s1), len2 = strlen(s2); Max = min(len1, len2) - 1; build(0,Max,1); printf("Case %d:\n",cas++); while(Q--){ scanf("%d",&id); if(id == 1){ scanf("%d %d %s",&id,&p,cc); update(id,p,cc[0],0,Max,1); } else{ scanf("%d",&p); int ans = query(p,Max,0,Max,1);//ans返回的是位置 if(ans == -1) printf("0\n"); else printf("%d\n",ans - p + 1); } } } return 0; }
相关文章推荐
- hdu 4339 Query 一道挺好的树状数组题(树状数组+二分思想)
- HDU-4339 Query(树状数组+二分)
- HDU 4339 Query [树状数组]
- HDU 4339 Query(树状数组+二分)
- HDU 1166 线段树模板&树状数组模板
- hdu 1166 线段树与树状数组入门 单点更新
- HDU 4638 - Group(树状数组 / 线段树)
- HDU 1394 (树状数组 & 线段树 两种做法)
- hdu 1116 线段树或树状数组(基础题)
- HDU - 1166 - 敌兵布阵(树状数组、线段树)
- hdu 1166(树状数组 或 线段树)
- HDU 1556 Color the ball【线段树及lazy思想】【树状数组】
- HDU 3333 Turing Tree(树状数组 || 线段树)
- HDU - 1556 Color the ball(树状数组 or 线段树)
- HDU 1166 敌兵布阵 我的第一棵树,线段树,树状数组。
- 【HDU】-1166-敌兵布阵(树状数组,线段树)
- HDU&nbsp;4339&nbsp;Query&nbsp;(线段树)
- HDU 5618 Jam's problem again(三维偏序,CDQ分治,树状数组,线段树)
- HDU 4638 多校第四场1007 离线询问,树状数组||线段树维护
- hdu 4031 attack 树状数组 线段树 两种做法