hdu--4339--线段树

很多时候  平常觉得很熟悉的一样东西穿上了一件外衣 我们就不认识了

其实 还是 我们不够熟悉。

这题的原型 就是给你一串由01组成的序列 可以随机修改某个固定位置的值<由0变1 由1变0> 然后就是要让我们求出从某个 x的左端点开始的最长连续1的数量

我们将这题 转换过来 就是对应坐标位置 假如2个值相同则为1 否则为0 然后我们每次的修改某个字符串的字符 也会对于该位置对应的序列值可能会发生变化 不一定 看具体修改情况

询问的话 就是刚刚说的 从x这个端点向右连续1的数量 当然包括它本身

这边 我觉得需要注意一点

tree[rt].Lson/Rson  你这边的Lson Rson都是指 rt所表示的区间下 从它的左边端点 与 右边端点出发的 连续1的数量

所以 假如我们存在查询的端点值x位于 rt<<1 就是rt的左子区间下 那我们就要注意判断了 如果这时候你的左子区间满足从左子区间右边数过来连续1的数量到底的坐标是<=L的

那么 我们在统计从x开始向右的连续1的数量的时候就应该继续是统计左子区间的同时还要加上右子区间 至于 右子区间具体有没有就看函数自己执行下去了 反正我们指令发出去了

但假如查询的x位于 rt<<1|1 就是rt的右子区间下 那就不需要那么麻烦了  就对于当前rt所表示的区间而言 rt<<1|1已经是最右边了  但是rt<<1|1可能它自身在进行判断的时候又会遇到刚刚的情况 x 位于 ( rt<<1|1)<<1 它的左子区间下 那就重复上面操作 就好了

单点更新 区间求值

  1 #include <iostream>
  2 #include <cstring>
  3 #include <algorithm>
  4 using namespace std;
  5
  6 const int size = 1000010;
  7 int len;
  8 char ss[size] , tt[size];
  9 int num[size];
 10 struct node
 11 {
 12     int L , R , Len;
 13     int Lone , Rone;
 14 }tree[size*4];
 15
 16 void init( )
 17 {
 18     len = min( strlen(ss) , strlen(tt) );
 19     memset( num , 0 , sizeof(num) );
 20     for( int i = 0 ; i<len ; i++ )
 21     {
 22         if( ss[i]==tt[i] )
 23             num[i+1] = 1;
 24     }
 25 }
 26
 27 void pushUp( int rt )
 28 {
 29     tree[rt].Lone = tree[rt<<1].Lone;
 30     tree[rt].Rone = tree[rt<<1|1].Rone;
 31     if( tree[rt<<1].Lone == tree[rt<<1].Len )
 32         tree[rt].Lone += tree[rt<<1|1].Lone;
 33     if( tree[rt<<1|1].Rone == tree[rt<<1|1].Len )
 34         tree[rt].Rone += tree[rt<<1].Rone;
 35 }
 36
 37 void build( int rt , int L , int R )
 38 {
 39     int M = ( L + R ) >> 1;
 40     tree[rt].L = L;
 41     tree[rt].R = R;
 42     tree[rt].Len = R - L + 1;
 43     if( L==R )
 44     {
 45         tree[rt].Lone = tree[rt].Rone = num[L];
 46         return ;
 47     }
 48     build( rt<<1 , L , M );
 49     build( rt<<1|1 , M+1 , R );
 50     pushUp( rt );
 51 }
 52
 53 void update( int rt , int L , int var )
 54 {
 55     int M = ( tree[rt].L + tree[rt].R ) >> 1;
 56     if( tree[rt].L == L && tree[rt].R == L )
 57     {
 58         tree[rt].Lone = tree[rt].Rone = var;
 59         return ;
 60     }
 61     if( L<=M )
 62         update( rt<<1 , L , var );
 63     else
 64         update( rt<<1|1 , L , var );
 65     pushUp( rt );
 66 }
 67
 68 int query( int rt , int L  )
 69 {
 70     int M = ( tree[rt].L + tree[rt].R ) >> 1;
 71     if( tree[rt].L == L )
 72         return tree[rt].Lone;
 73     if( L<=M )
 74     {
 75         if( tree[rt<<1].R - tree[rt<<1].Rone + 1 <= L )
 76         {
 77             return query( rt<<1 , L ) + query( rt<<1|1 , M+1 );
 78         }
 79         return query( rt<<1 , L  );
 80     }
 81     else
 82     {
 83         return query( rt<<1|1 , L );
 84     }
 85 }
 86
 87 int main()
 88 {
 89     cin.sync_with_stdio(false);
 90     int t , op , a , i , k , ans;
 91     char c;
 92     int q;
 93     cin >> t;
 94     for( int Case = 1 ; Case<=t ; Case++ )
 95     {
 96         cin >> ss >> tt;
 97         init( );
 98         build( 1 , 1 , len );
 99         cin >> q;
100         cout << "Case " << Case << ":" << endl;
101         while( q-- )
102         {
103             cin >> op;
104             if( op==1 )
105             {
106                 cin >> a >> i >> c; // 第 a 行的 str[i] 变成 (char)c;
107                 if( i>=len )
108                     continue;
109                 if( a==1 ) //ss
110                 {
111                     ss[i] = c;
112                     if( c==tt[i] )
113                         num[i+1] = 1;
114                     else
115                         num[i+1] = 0;
116                 }
117                 else
118                 {
119                     tt[i] = c;
120                     if( c==ss[i] )
121                         num[i+1] = 1;
122                     else
123                         num[i+1] = 0;
124                 }
125                 update( 1 , i+1 , num[i+1] );
126             }
127             else
128             {
129                 cin >> k;
130                 ans = query( 1 , k+1 );
131                 cout << ans << endl;
132             }
133         }
134     }
135     return 0;
136 }

today:

  r = a ( 1 - sinθ )

时间: 2024-10-11 13:59:54

hdu--4339--线段树的相关文章

HDU 4339 线段树区间合并

Query Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2573    Accepted Submission(s): 851 Problem Description You are given two strings s1[0..l1], s2[0..l2] and Q - number of queries.Your task

hdu 4339 线段树+二分

题意是给你两个字符串    进行两种操作   1: 修改其中一个字符串里的某个字符2:   询问从i起两个字符串最多由多少个是相同的: 先说一下做之前的想法   ,我是看别人介绍树状数组是看到这道题的    本也想用树状数组做  ,没想上去    然后就改为线段树了   ,有很明显的点更新,区间查询,所以选择线段树: 思路:  每个节点num[] 存3个值       p1  p2  flash   flash表示当前节点两个字符串是不是一样的   若是则为1否则为0    p1 p2为当前两个

HDU 4893 线段树裸题

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2512    Accepted Submission(s): 751 Problem Description Recently, Doge got a funny birthday present from his new friend, Pro

HDU 4902 线段树(区间更新)

Nice boat Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 353    Accepted Submission(s): 169 Problem Description There is an old country and the king fell in love with a devil. The devil alw

hdu 4893 线段树 --- 也是两个变 类似双标记

http://acm.hdu.edu.cn/showproblem.php?pid=4893 开始的时候,我按双标记,WA了一下午,搞不定,我是用的两个标记add--表示当前结点中有值发生变化,flag,斐波那契的懒惰标记,但是估计是我自己处理的有问题,一直不对 参考了别人的代码,写法还是很不错的,Add变量维护的是,完全变成Fibonacci的时候的和,---回头我再重新写一遍 #include <cstdio> #include <cstring> #include <a

HDU 4902 线段树||暴力

给定一个序列,两种操作 1:把一段变成x. 2:把一段每个数字,如果他大于x,就变成他和x的gcd,求变换完后,最后的序列. 线段树解法:用lazy标记下即可,优化方法还是很巧妙的, Accepted 4902 515MS 3308K 1941 B C++ #include "stdio.h" #include "string.h" struct node { int l,r,x;// 在叶子节点代表值,树节点代表成端更新的lazy操作. }data[400010]

HDU 4302 线段树单点更新,维护区间最大最小值

http://acm.hdu.edu.cn/showproblem.php?pid=4302 Problem Description Holedox is a small animal which can be considered as one point. It lives in a straight pipe whose length is L. Holedox can only move along the pipe. Cakes may appear anywhere in the p

HDU 3397 线段树 双懒惰标记

这个是去年遗留历史问题,之前思路混乱,搞了好多发都是WA,就没做了 自从上次做了大白书上那个双重懒惰标记的题目,做这个就思路很清晰了 跟上次大白上那个差不多,这个也是有一个sets标记,代表这个区间全部置为0或者1,没有置位的时候为-1 还有个rev标记,代表翻转操作,0代表当前不翻,1代表当前翻 要注意一下优先级,发现有不同的弄法,我是这个弄得,有set操作的时候,set标记设值,并把当前节点的rev标记设为0,因为不管要不要rev,当前set操作肯定直接覆盖了 rev操作不改变set操作,在

hdu 2795 线段树--点更新

http://acm.hdu.edu.cn/showproblem.php?pid=2795 多校的第一场和第三场都出现了线段树,比赛期间没做,,这两天先做几道热身下,然后31号之前把那两道多校的线段树都搞了,这是一道热身题 关键是建模: 首先一定看清楚题目构造的场景,看有什么特点--------会发现,如果尽量往左上放置的话,那么由于 the i-th announcement is a rectangle of size 1 * wi.,完全可以对h建立线段树,表示一行,结点里的l,r就表示

HDU 1698 线段树(区间染色)

Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 16255    Accepted Submission(s): 8089 Problem Description In the game of DotA, Pudge’s meat hook is actually the most horrible thing f