码迷,mamicode.com
首页 > 其他好文 > 详细

【NOIP模拟】board(线段树维护二进制,树序号化为二进制)

时间:2017-07-21 01:14:04      阅读:273      评论:0      收藏:0      [点我收藏+]

标签:tld   struct   zmq   wim   i2c   ajp   avd   size   cout   

题目背景

SOURCE:NOIP2016-RZZ-2 T3

题目描述

给出这样一棵“二叉树”:

    • 每个节点有左右两个儿子,并如下定义每个节点的高度:假设父亲节点的高度为 h ,那么他的两个儿子的节点的高度都是 h + 1 ,相同高度的所有节点称作一层。
    • 每个节点的左儿子的子树都在右儿子的子树的左边,每一层相邻的两个节点之间有一条边。

下面是一个例子:

    技术分享

每一条图上的路径用一个字符串表示,字符串中的每一个字符表示一个移动。字符仅包含如下五种:

    • 1:表示移动到当前节点的左儿子
    • 2:表示移动到当前节点的右儿子
    • U:表示移动到当前节点的父亲节点
    • L:表示移动到当前节点同层的左边的节点(保证当前节点在这一层中不是最左边的节点)
    • R:表示移动到当前节点同层的右边的节点(保证当前节点在这一层中不是最右边的节点)

用一条路径来表示这条路径的终点,例如路径:221LU 就表示上图中的节点 A 。

给出两条路径,你的任务是求出着两条路径的终点之间的最短路。

输入格式

输入两行,每行一个字符串,分别表示两条路径。

输出格式

输出一行一个整数,表示能得到的串的总数。

样例数据 1

输入

221LU 
12L2

输出

3

备注

【数据规模与约定】

用 D 表示所有经过的节点中,深度最大的节点的深度;S 表示输入字符串的最大长度。对于 10% 的数据,D≤10。对于 30% 的数据,D≤50。
对于 50% 的数据,D≤1000。
对于 70% 的数据,D≤20000。
对于 100% 的数据,D≤100000;S≤100000。

【题目分析】

 

【code】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;

const int D = 100005, S = 100005;

char s[S], t[S];
int ls, lt, ans, ret;
struct node{
    int len, sum, tag;
    node():len(0), sum(0), tag(0){}
};
namespace SegTree{
    node tr[D * 4];
    inline void upt(int k){
        int lc = k << 1, rc = k << 1 | 1;
        tr[k].sum = tr[lc].sum + tr[rc].sum;
    }
    inline void cover(int k, int v){
        tr[k].sum = (v - 1) * tr[k].len;
        tr[k].tag = v;
    }
    inline void pushDown(int k){
        int lc = k << 1, rc = k << 1 | 1;
        if(tr[k].tag){
            cover(lc, tr[k].tag);
            cover(rc, tr[k].tag);
            tr[k].sum = (tr[k].tag - 1) * tr[k].len;
            tr[k].tag = 0;
        }
    }
    inline void build(int k, int l, int r){
        tr[k].len = r - l + 1;
        if(l == r) return;
        int mid = l + r >> 1, lc = k << 1, rc = k << 1 | 1;
        build(lc, l, mid);
        build(rc, mid + 1, r);
        upt(k);
    }
    inline void modify(int k, int l, int r, int x, int y, int v){
        if(x <= l && r <= y){
            cover(k, v);
            return;
        }
        pushDown(k);
        int mid = l + r >> 1, lc = k << 1, rc = k << 1 | 1;
        if(x <= mid) modify(lc, l, mid, x, y, v);
        if(y > mid) modify(rc, mid + 1, r, x, y, v);
        upt(k);
    }
    inline int query_1(int k, int l, int r, int pos){
        if(pos < l) return 0;
        if(tr[k].sum == 0) return 0; 
        if(l == r) return tr[k].sum == 1 ? l : 0;
        int mid = l + r >> 1, lc = k << 1, rc = k << 1 | 1;
        pushDown(k);
        int ret = 0;
        ret = query_1(rc, mid + 1, r, pos);
        if(!ret) ret = query_1(lc, l, mid, pos); 
        return ret;
    }
    inline int query_0(int k, int l, int r,int pos){
        if(pos < l) return 0;
        if(tr[k].sum == tr[k].len) return 0;
        if(l == r) return tr[k].sum == 0 ? l : 0;
        pushDown(k);
        int ret = 0;
        int mid = l + r >> 1, lc = k << 1, rc = k << 1 | 1;
        ret = query_0(rc, mid + 1, r, pos);
        if(!ret) ret = query_0(lc, l, mid, pos);
        return ret;
    }
    inline void treeExport(int k, int l, int r, char *p){
        if(l == r){
            p[l] = tr[k].sum + 0;
//            if(l == 1) cout<<"!!!!!!!"<<p[l]<<endl;
            return;
        }
        pushDown(k);
        int mid = l + r >> 1, lc = k << 1, rc = k << 1 | 1;
        treeExport(lc, l, mid, p);
        treeExport(rc, mid + 1, r, p);
    }
}using namespace SegTree;

inline void loadIn(char *f, int &q){
    static char p[S];
    scanf("%s", p + 1);
    int maxx = strlen(p + 1);
    q = 0;
    memset(tr, 0, sizeof tr);
    build(1, 1, maxx);
    for(int i = 1; i <= maxx; i++){
        switch(p[i]){
            case 1:{
                    q++;
                    modify(1, 1, maxx, q, q, 1);
                }
                break;
            case 2:{
                    q++;
                    modify(1, 1, maxx, q, q, 2);
                }
                break;
            case U:{
                    q--;
                }
                break;
            case R:{
                    int first_0 = query_0(1, 1, maxx, q);
                    modify(1, 1, maxx, first_0, first_0, 2);
                    modify(1, 1, maxx, first_0 + 1, q, 1);
                }
                break;
            case L:{
                    int first_1 = query_1(1, 1, maxx, q);
                    modify(1, 1, maxx, first_1, first_1, 1);
                    modify(1, 1, maxx, first_1 + 1, q, 2);
                }
                break;
            default:break;
        }
    }
    treeExport(1, 1, maxx, f);
}

inline int Re(){
    int i = 0, f = 1; char ch = getchar();
    for(; (ch < 0 || ch > 9) && ch != -; ch = getchar());
    if(ch == -) ch = getchar(), f = -1;
    for(; ch >= 0 && ch <= 9; ch = getchar())
        i = (i << 3) + (i << 1) + (ch - 0);
    return i * f;
}

inline void Wr(int x){
    if(x < 0) putchar(-), x = -x;
    if(x > 9) Wr(x / 10);
    putchar(x % 10 + 0);
}

int main(){
    loadIn(s, ls), loadIn(t, lt);
    ans = abs(ls - lt);
    int n = min(ls, lt), dis = 0;
    ret = 2 * n;
    for(int i = 1; i <= n; i++){
        if(s[i] == t[i]) dis = dis * 2;
        else if(s[i] == 0 && t[i] == 1) dis = 2 * dis + 1;
        else if(s[i] == 1 && t[i] == 0){
            dis = 2 * dis - 1;
            if(dis < 0) dis = -dis, swap(s, t);
        }
        if(dis > ret) break;
        ret = min(ret, dis + 2 * (n - i));
    }
//    cout<<s+1<<" "<<t + 1<<endl;
//    Wr(ans), putchar(‘ ‘);
    Wr(ans + ret), putchar(\n);
    return 0;
}

 

【NOIP模拟】board(线段树维护二进制,树序号化为二进制)

标签:tld   struct   zmq   wim   i2c   ajp   avd   size   cout   

原文地址:http://www.cnblogs.com/CzYoL/p/7215464.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!