线段树 BZOJ NOI 十连测

【问题描述】

小𝐷写完了随机哈夫曼树,凭信仰开始补觉,想起了在ZJOI见过的一
个模型:
∙ 给出一个长度为𝑛的数组𝑎,1 ∼ 𝑛标号。
∙ 𝑚个操作,每个操作有两个参数𝑙𝑖, 𝑟𝑖,表示将区间[𝑙𝑖, 𝑟𝑖]中的所有数修
改为这个区间的最大值。
这个问题可以简单地用线段树来完成,现在小𝐷将这个问题扩展了一
下。
给出一个长度为𝑛的初始数组𝑎,以及𝑚个操作,需要维护:
∙ 求依次进行编号为[𝐿,𝑅]的这一段操作后𝑎𝑘的值。这些询问互相独立,
即可以理解为“假如进行这一段操作后,𝑎𝑘的值会变成多少”。
∙ 将𝑎𝑢的值修改为𝑣,即修改初始数组,这次修改会影响它之后的所有
询问。
可以参考输入格式来帮助理解题意。

【输入格式】
从文件segment.in中读入数据。
第一行,三个正整数𝑛, 𝑚, 𝑞,表示数组长度,操作数和询问数。
第二行,𝑛个正整数𝑎𝑖。

【输出格式】
输出到文件segment.out中。
对于每次询问输出一行一个正整数,表示“假如进行编号为[𝐿,𝑅]的这
一段操作后𝑎𝑘的值”。

【数据规模】
对于10%的数据,𝑛, 𝑚, 𝑞 ≤ 100。
对于30%的数据,𝑛, 𝑚, 𝑞 ≤ 10000。
对于另20%的数据,询问时𝐿 = 1。
对于80%的数据,𝑛, 𝑚, 𝑞 ≤ 50000(包含前一档𝐿 = 1)。
对于100%的数据,𝑛, 𝑚, 𝑞 ≤ 105,1 ≤ 𝑎𝑖, 𝑣 ≤ 105。

SOL:

  我们倒着做,发现最后的答案是原序列的一段区间的max,我们倒着加操作可以保证这个L与R单调。我们把L与R差点,

我们考虑用主席树分别维护L与R,强行套个倍增就好了。

#include<bits/stdc++.h>
using namespace std;
#define N 300007
#define Mid (l+r>>1)
#define Max(a,b) ((a)>(b)?(a):(b))
#define sight(x) ('0'<=x&&x<='9')
int ans,anw,n,m,q,root[N],L[N][21],R[N][21],op,l,r,w,LL,RR;
inline void read(int &x){
    static char c;
    for (c=getchar();!sight(c);c=getchar());
    for (x=0;sight(c);c=getchar())x=x*10+c-48;
}
struct Node{
    int l,r;
}qu[N];
void write(int x){if (x<10) {putchar('0'+x); return;} write(x/10); putchar('0'+x%10);}
inline void writeln(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar('\n'); }
inline void writel(int x){ if (x<0) putchar('-'),x*=-1; write(x); putchar(' '); }
struct Tree{ 
    int t[N<<2];
    void build(int node,int l,int r){
        if (l==r) {read(t[node]); return;} 
        build(node<<1,l,Mid); build(node<<1|1,Mid+1,r);
        t[node]=Max(t[node<<1],t[node<<1|1]);
    }
    void change(int node,int l,int r,int id,int ch){
        if (l==r) {t[node]=ch; return;}
        if (id<=Mid) change(node<<1,l,Mid,id,ch); 
        else change(node<<1|1,Mid+1,r,id,ch);
        t[node]=Max(t[node<<1],t[node<<1|1]);
    }
    void Qu(int node,int l,int r,int L,int R){
        if (L<=l&&r<=R) {ans=Max(ans,t[node]); return;}
        if (L<=Mid) Qu(node<<1,l,Mid,L,R);
        if (Mid<R)  Qu(node<<1|1,Mid+1,r,L,R);
    }
}T1;
struct Te{
    int l,r,col;
};
struct TimeTree{
    Te T[N<<4];int tot;
    void add(int p,int &now,int l,int r,int L,int R,int dla){
        now=++tot; T[now]=T[p]; 
        if (L<=l&&r<=R) {T[now].col=dla; return;}
        if (L<=Mid) add(T[p].l,T[now].l,l,Mid,L,R,dla);
        if (Mid<R) add(T[p].r,T[now].r,Mid+1,r,L,R,dla);
    }
    void Qu(int X,int l,int r,int x){
        ans=Max(ans,T[X].col);
        if (l==r) return;
        if (x<=Mid) Qu(T[X].l,l,Mid,x);
        else Qu(T[X].r,Mid+1,r,x);
    }
}T2;
struct UnTree{
    int col[N<<2];
    void add(int node,int l,int r,int L,int R,int dla){
        if (L<=l&&r<=R){ col[node]=dla;return;}
        if (L<=Mid) add(node<<1,l,Mid,L,R,dla);
        if (R>Mid) add(node<<1|1,Mid+1,r,L,R,dla);
    }
    void Qu(int X,int l,int r,int x){
        ans=Max(ans,col[X]);
        if (l==r) return;
        if (x<=Mid) Qu(X<<1,l,Mid,x);
        else Qu(X<<1|1,Mid+1,r,x);
    }
}T3;
signed main () {
    freopen("segment.in","r",stdin);
    freopen("segment.out","w",stdout);
    read(n); read(m); read(q);
    T1.build(1,1,n);
    for (int i=1;i<=m;i++) read(qu[i].l), read(qu[i].r);
    for (int i=1;i<=m;i++) 
     T2.add(root[i-1],root[i],1,n,qu[i].l,qu[i].r,i);
    for (int i=1;i<=m;i++) {
        ans=0; T3.Qu(1,1,n,qu[i].l); L[i][0]=ans;
        ans=0; T3.Qu(1,1,n,qu[i].r); R[i][0]=ans;
        T3.add(1,1,n,qu[i].l,qu[i].r,i);
    }
    for (int i=1;i<=19;i++)
     for (int j=1;j<=m;j++) {
         L[j][i]=L[L[j][i-1]][i-1];
         R[j][i]=R[R[j][i-1]][i-1];
     }
    while (q--) {
        read(op); read(l); read(r);
        if (op&1) T1.change(1,1,n,l,r);
        else {
            read(w);
            ans=0; T2.Qu(root[r],1,n,w); anw=ans;
            if (ans>=l) {
                for (int i=19;~i;i--) if (L[ans][i]>=l) ans=L[ans][i];
                for (int i=19;~i;i--) if (R[anw][i]>=l) anw=R[anw][i];
                LL=qu[ans].l; RR=qu[anw].r; ans=0; T1.Qu(1,1,n,LL,RR);
            }else ans=0,T1.Qu(1,1,n,w,w);
            writeln(ans);
        }
    }
    return 0;
}

 

posted @ 2018-03-08 20:47  泪寒之雪  阅读(433)  评论(0编辑  收藏  举报