hdu 4391 线段树 优化

2012 多校第十场,这个题目比赛的时候我直接在每个节点里面开了一个map,结果毫无疑问MLE 了,比赛之后看了结题报告说是 分段哈希,没学过,后来听说线段树稍微剪枝一下就能过,换了一下思路,确实就能过了,每个节点也不需要记录每种颜色的个数了,只需要记录最大的编号和最小的就可以了。。

#include<iostream>
#include<algorithm>
using namespace std;

#define lson u<<1
#define rson u<<1|1
#define MAXN 100005

int a[MAXN];

struct Node{
    int lef,rig;
    int minc,maxc;//min color..max color..
    int color;
}T[MAXN<<2];

void PushUp(int u){
    if(T[u].lef==T[u].rig)return;
    if(T[lson].color==T[rson].color&&T[lson].color!=-1)T[u].color=T[lson].color;
    else T[u].color=-1;
    T[u].minc=min(T[lson].minc,T[rson].minc);
    T[u].maxc=max(T[lson].maxc,T[rson].maxc);
}

void PushDown(int u){
    if(T[u].color!=-1){
        T[lson].color=T[u].color;
        T[rson].color=T[u].color;
        T[lson].minc=T[lson].maxc=T[u].color;
        T[rson].minc=T[rson].maxc=T[u].color;
        T[u].color=-1;
    }
}

void Build(int u,int l,int r){
    T[u].lef=l;
    T[u].rig=r;
    T[u].color=-1;
    if(l==r){
    	T[u].minc=T[u].maxc=T[u].color=a[l];
    	return;
    }
    int mid=(l+r)>>1;
    Build(lson,l,mid);
    Build(rson,mid+1,r);
    PushUp(u);
}

void Update(int u,int l,int r,int color){
	if(color==T[u].color)return;//剪枝..
    //PushDown(u);
    if(l<=T[u].lef&&T[u].rig<=r){
        T[u].color=color;
        T[u].minc=T[u].maxc=color;
        return;
    }
    else {
        PushDown(u);
        if(l<=T[lson].rig)Update(lson,l,r,color);
        if(r>=T[rson].lef)Update(rson,l,r,color);
        PushUp(u);
    }
}

int Query(int u,int l,int r,int color){
    //PushDown(u);
    if(T[u].minc>color||T[u].maxc<color||(T[u].color!=color&&T[u].color!=-1))return 0;
    if(l<=T[u].lef&&T[u].rig<=r&&T[u].color==color)return T[u].rig-T[u].lef+1;
    else {
        PushDown(u);
        if(l>=T[rson].lef)return Query(rson,l,r,color);
        if(r<=T[lson].rig)return Query(lson,l,r,color);
        int lc=Query(lson,l,T[lson].rig,color);
        int rc=Query(rson,T[rson].lef,r,color);
        return lc+rc;
    }
}

int main(){
    int n,m;
    while(scanf("%d%d",&n,&m)==2){
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        Build(1,1,n);

        int cmd,a,b,c;

        while(m--){
            scanf("%d%d%d%d",&cmd,&a,&b,&c);
            a++;b++;
            if(cmd==1)Update(1,a,b,c);
            else {
                printf("%d\n",Query(1,a,b,c));
            }
        }
    }
}



你可能感兴趣的:(c,优化,struct,cmd,query,Build)