POJ3368

 摘要:

话说看Discuss看了半天,茫茫然不知所云,硬着头皮自己写了个线段树,居然过了。。。

#include <iostream>
#include <stdio.h>
using namespace std;

typedef struct Node{
    int left;
    int right;
    int left_value;
    int right_value;
    int value;
    int left_num;
    int right_num;
    int num;
    Node *left_child;
    Node *right_child;
    void Construct(int, int);
    void Insert(int, int, int);
    int Calculate(int, int);
}Node;
const int size = 100000;

Node sTree[size*3];
Node *root = &sTree[0];
int len = 1;
int input[size+1] = {0};

void Node::Construct(int l, int r)
{
    left = l;
    right = r;
    left_value = right_value = value = 0;
    left_num = right_num = num = 0;
   
    if( l == r ){
        left_child = right_child = NULL;
        return;
    }
   
    left_child = &sTree[len++];
    right_child = &sTree[len++];
   
    int mid = (left + right) >> 1;
    left_child->Construct(l, mid);
    right_child->Construct(mid+1, r);
}

void Node::Insert(int l, int r, int v)
{
    if( l==left ){
        left_num = r - l + 1;
        left_value = v;   
    }
    if( r==right){
        right_num = r - l + 1;
        right_value = v;
    }
    if( num < (r - l + 1) ){
        num = r - l + 1;
        value = v;   
    }
   
    if(left==l && right==r){
        return;
    }
   
    int mid = (left + right) >> 1;
    if( l > mid ){
        right_child->Insert(l, r, v);
        return;
    }
    if( r <= mid){
        left_child->Insert(l, r, v);
        return;
    }

    left_child->Insert(l, mid, v);
    right_child->Insert(mid+1, r, v);   
}

int Node::Calculate(int l, int r)
{
    //cout << "calculate:" << left << "," << right << "/t" << l << "," << r << endl;

    if( left==l && right==r){
        return num;   
    }
    if( num == right-left+1 ){
        return r - l + 1;
    }

    int mid = (left + right) >> 1;

    if( l > mid ){
        return right_child->Calculate(l, r);
    }
    if( r <= mid){
        return left_child->Calculate(l, r);
    }
   
    int rt1, rt2, rt3;
    rt1 = rt2 = rt3 = 0;
    rt1 = left_child->Calculate(l, mid);
    rt2 = right_child->Calculate(mid+1, r);
   
    if(left_child->right_value == right_child->left_value){
        rt3 = min(left_child->right_num, mid-l+1) + min(right_child->left_num, r-mid);
    }
   
    rt1 = max(rt1, rt2);
    rt1 = max(rt1, rt3);   
       
    return rt1;   
}


int main()
{
    while(true){
        int n, q;
        scanf("%d", &n);
        if(n == 0){
            break;
        }
        scanf("%d", &q);
       
        len = 1;
        root->Construct(1, n);
   
        int i=1;
        for(int j=1; j<=n; j++){
            scanf("%d", &input[j]);
            if(input[j] != input[i]){
                root->Insert(i, j-1, input[i]);
                i=j;   
            }
        }
        root->Insert(i, n, input[i]);

        for(int j=1; j<=q; j++){
            int left, right;
            scanf("%d%d", &left, &right);
            printf("%d/n", root->Calculate(left, right));
        }
    }   

    return 0;   
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值