zoukankan      html  css  js  c++  java
  • 2019南昌网络赛  I. Yukino With Subinterval 树状数组套线段树

    I. Yukino With Subinterval

    题目链接:

    Problem Descripe

    Yukino has an array (a_1, a_2 cdots a_n). As a tsundere girl, Yukino is fond of studying subinterval.

    Today, she gives you four integers $l, r, x, y $, and she is looking for how many different subintervals ([L, R]) are in the interval ([l, r])that meet the following restraints:

    1. (a_L =a_{L+1} =cdots=a_R), and for any $ iin [L,R], x le a_i le y$.
    2. The length of such a subinterval should be maximum under the first restraint.

    Note that two subintervals ([L_1,R_1] , [L_2,R_2]) are different if and only if at least one of the following formulas is true:

    1. (L1 cancel= L2)
    2. (R1 cancel= R2)

    Yukino, at the same time, likes making tricks. She will choose two integers (pos,v), and she will change (a_{pos}) to (v).

    Now, you need to handle the following types of queries:

    • (1 pos v) : change (a_{pos}) to $v $
    • (2) (l r x y): print the number of legal subintervals in the interval ([l, r])

    Input

    The first line of the input contains two integers (n, m (1 le n, m le 2 imes 10^5))– the numbers of the array and the numbers of queries respectively.

    The second line of the input contains nnn integers (a_i (1 le a_i le n)).

    For the next mmm line, each containing a query in one of the following queries:

    • (1) (pos) (v (1 le pos, v le n)): change (a_{pos}) to (v)
    • (2 l r x y (1 le l le r le n) (1 le x le y le n)): print the number of legal subintervals in the interval ([l,r])

    Output

    For each query of the second type, you should output the number of legal subintervals in the interval ([l, r]).

    样例输入

    6 3
    3 3 1 5 6 5
    2 2 3 4 5
    1 3 2
    2 1 6 1 5

    样例输出

    0
    4

    样例解释

    For the first operations, there are (3) different subintervals (([2, 2],[3, 3],[2,3]))in the interval ([2, 3]), but none of them meets all the restraints.

    For the third operations, the legal subintervals in interval ([1, 6]) are: ([1, 2], [3, 3], [4, 4], [6, 6])

    Notes that although subintervals ([1,1]) and ([2,2]) also meet the first restraint, we can extend them to subinterval ([1, 2]). So the length of them is not long enough, which against the second one.

    题意

    给你一个序列,提供两种操作

    • (1) (pos) (v (1 le pos, v le n)): 将 (a_{pos}) 改为 (v)
    • (2 l r x y (1 le l le r le n) (1 le x le y le n)): 输出([l,r]) 中权值(in [x,y]) 的个数。特别注意一段连续相同的数只算一次

    题解

    树套树(n)年前打的,早就忘了,于是直接跳过,其实这就是一道可修改区间第k大模板题吧,如果不会的可以去luogu学习一下。

    模板传送门:https://www.luogu.org/problem/P3380

    这题唯一要解决的就是怎么处理连续段只算一次的问题了。我是树状数组套线段树,于是如果(a[i]=a[i-1])那么就不处理。

    还有几个需要注意的地方

    1. 如果改变了(a[i])的值,记得更改(a[i-1])(a[i+1])
    2. 对于区间([l,r]),记得特判(a[l]),可能(a[l]=a[l-1]),但是这时也要算

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define INF 0x7f7f7f7f
    #define N 200050
    template<typename T>void read(T&x)
    {
        ll k=0; char c=getchar();
        x=0;
        while(!isdigit(c)&&c!=EOF)k^=c=='-',c=getchar();
        if (c==EOF)exit(0);
        while(isdigit(c))x=x*10+c-'0',c=getchar();
        x=k?-x:x;
    }
    void read_char(char &c)
    {while(!isalpha(c=getchar())&&c!=EOF);}
    int n,m,treeNode;
    int a[N],ql[20],qr[20];
    struct Tree{int ls,rs,sum;}tr[N*150];
    void update(int&x,int p,int tt,int l,int r)
    {
        if (x==0)x=++treeNode;
        tr[x].sum+=tt;
        if (l==r)return;
        int mid=(l+r)>>1;
        if (p<=mid)update(tr[x].ls,p,tt,l,mid);
        else update(tr[x].rs,p,tt,mid+1,r);
    }
    void change(int x,int p,int tt)
    {while(x<=n)update(x,p,tt,1,n+1),x+=x&-x;}
    void getRt(int l,int r)
    {
        ql[0]=qr[0]=0;
        while(l)ql[++ql[0]]=l,l-=l&-l;
        while(r)qr[++qr[0]]=r,r-=r&-r;
    }
    int getSum()
    {
        int ans=0;
        for(int i=1;i<=ql[0];i++)ans-=tr[tr[ql[i]].ls].sum;
        for(int i=1;i<=qr[0];i++)ans+=tr[tr[qr[i]].ls].sum;
        return ans;
    }
    void move_L()
    {
        for(int i=1;i<=ql[0];i++)ql[i]=tr[ql[i]].ls;
        for(int i=1;i<=qr[0];i++)qr[i]=tr[qr[i]].ls;
    }
    void move_R()
    {
        for(int i=1;i<=ql[0];i++)ql[i]=tr[ql[i]].rs;
        for(int i=1;i<=qr[0];i++)qr[i]=tr[qr[i]].rs;
    }
    int _Rank(int p,int l,int r)
    {
        if (l==r)return 0;
        int mid=(l+r)>>1,tp=getSum();
        if (p<mid){move_L();return _Rank(p,l,mid);}
        move_R(); return tp+_Rank(p,mid+1,r);
    }
    int Rank(int l,int r,int k)
    {
        getRt(l-1,r);
        return _Rank(k-1,1,n+1);
    }
    void work()
    {
        int id,pos,v,l,r,x,y;
        read(n); read(m);
        treeNode=n;
        for(int i=1;i<=n;i++)read(a[i]);
        for(int i=1;i<=n;i++)if (a[i]!=a[i-1])change(i,a[i],1);
        for(int i=1;i<=m;i++)
        {
            read(id);
            if (id==1)
            {
                read(pos); read(v);
                if (a[pos]!=a[pos-1])change(pos,a[pos],-1);
                if (v!=a[pos-1])change(pos,v,1);
                if (a[pos]==a[pos+1])change(pos+1,a[pos+1],1);
                if (v==a[pos+1])change(pos+1,a[pos+1],-1);
                a[pos]=v;
            }
            if (id==2)
            {
                read(l); read(r); read(x); read(y);
                int ans=-Rank(l,r,x)+Rank(l,r,y+1);
                if (a[l]==a[l-1]&&x<=a[l]&&a[l]<=y)ans++;
                printf("%d
    ",ans);
            }
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("aa.in","r",stdin);
    #endif
      work();
    }
    
    
  • 相关阅读:
    Java实现 LeetCode 242 有效的字母异位词
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 212 单词搜索 II
    Java实现 LeetCode 344 反转字符串
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
    Java实现 洛谷 P1208 [USACO1.3]混合牛奶 Mixing Milk
  • 原文地址:https://www.cnblogs.com/mmmqqdd/p/11508864.html
Copyright © 2011-2022 走看看