hdu – 4339 – Query – 樹狀數組||線段樹

來源:互聯網
上載者:User

用樹狀數組和二分尋找連續的1.http://acm.hdu.edu.cn/showproblem.php?pid=4339

做題過程:

        開始做的時候發現自己以前做過。索性做吧。神奇的是我發現我以前用樹狀數組和線段是各A了一遍。真是勤奮的孩子。

        我對這題的二分很是反感,記得以前做的時候就二分了很久來著,而且只是二分不會。。。。。。

        對於線段樹的作法我已經淡忘了,只記得樹狀數組的。明天來把線段樹的再一寫。

今天我才意識到,單點更新這東西是更新到底層,複雜度很高的,沒有什麼優越性。

/*Pro: 0Sol: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 ) >> 1using 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;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.