• P6859 蝴蝶与花 题解


    P6859 蝴蝶与花 题解

    题目大意:

    给定一个长度为 (n) 的序列 (a_i) ,(a_iin { 1,2 }) ,每次操作给出两种类型的操作:

    • 修改格式:(C i val)(a_i) 改为 (valin {1,2})
    • 查询格式:(A K) ,查询整个序列有无一个子串和为 (K),输出所有方案中 (L) 最小的。

    分析:

    首先,设要求查询的和为 (K) ,首先当 (K>sum||K=0) 时是肯定无解的。(此时 (sum) 指整个序列的和)

    因为要求左端点最小:

    很容易想到从 (1) 开始,我们先找到以 (1) 为左端点,子串和 (geq K) 的最小的右端点记作 (R)

    这一点可以通过一个线段树上二分在 (Theta(log n )) 的时间解决,修改也就是一个简单的单点修改。

    此时查询到的子串和一定为 (K)(K+1) ,这点可以通过反证法证明。

    若子段和为 (K) 则证明已经找到了答案,着重解决的肯定是子段和为 (K+1) 的部分。

    为了保证左端点最小,并且保持着当前的子串和为 (K+1) 不变,选择两个端点同时向右移动。

    在两个端点向右移动的过程中,如果有一个端点的值为 (1) ,则找到了答案。

    因为它们都从原本的 (2) 走到了 (1) 。(右端点的值一定为 (2)

    而左端点可以近似的看作从 (2) 走到了 (1)

    所以答案就是离左端点最近的 (1) ,或者右端点更近的 (1)

    用一个 set 维护即可。

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>
    inline void read(T &x){
        x=0;char ch=getchar();bool f=false;
        while(!isdigit(ch)) f|=ch=='-',ch=getchar();
        while(isdigit(ch))  x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=f?-x:x;return;
    }
    template <typename T>
    inline void print(T x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) print(x/10);
        putchar(x%10^48);return;
    }
    const int N=2e6+3,INF=1e9;
    int n,m,a[N],nxt[N],pre[N];
    struct node{
        int sum,lazy;
        #define sum(x)  c[x].sum
        #define lazy(x) c[x].lazy
    }c[N<<2];
    #define lc x<<1
    #define rc x<<1|1
    inline void Push_up(int x){sum(x)=sum(lc)+sum(rc);return;}
    inline void Build(int x,int l,int r){
        if(l==r){sum(x)=a[l];return;}
        int mid=(l+r)>>1;Build(lc,l,mid),Build(rc,mid+1,r);
        Push_up(x);return;
    }
    inline void Modify(int x,int l,int r,int to,int d){
        if(l==r){sum(x)=d;return;}
        int mid=(l+r)>>1;if(mid>=to) Modify(lc,l,mid,to,d);
        else Modify(rc,mid+1,r,to,d);
        Push_up(x);return;
    }
    int res=0;
    inline int Query(int x,int l,int r,int k){
        if(l==r){res+=a[l];return l;}
        int mid=(l+r)>>1;
        if(sum(lc)>=k)  return Query(lc,l,mid,k);
        else{res+=sum(lc);return Query(rc,mid+1,r,k-sum(lc));}
    }
    set<int> loc;
    int main(){
        read(n),read(m);
        for(register int i=1;i<=n;++i){read(a[i]);if(a[i]==1) loc.insert(i);}
        Build(1,1,n);
        while(m--){
            char op[2];scanf("%s",op);
            if(op[0]=='A'){
                int x;read(x);
                if(x>sum(1)||x==0){puts("none");continue;}
                res=0;int R=Query(1,1,n,x);
                if(res==x){print(1),putchar(' '),print(R),putchar('
    ');continue;}
                int loc1=INF,loc2=INF;
                if(!loc.empty())    loc1=*loc.begin();
                set<int>::iterator it=loc.lower_bound(R);
                if(it!=loc.end())   loc2=*it;
                int len=loc2-R+1;
                if(loc2==INF&&R+loc1-1>n){puts("none");continue;}
                if(loc1>=len) print(len),putchar(' '),print(loc2),putchar('
    ');
                else print(loc1+1),putchar(' '),print(R+loc1-1),putchar('
    ');
            }
            else{
                int i,val;read(i),read(val);
                if(a[i]==1) loc.erase(i);
                if(val==1)  loc.insert(i);
                a[i]=val;Modify(1,1,n,i,val);
            }
        }
    
        return 0;
    }
    
    
  • 相关阅读:
    设置IIS7/IIS7.5的FTP支持断点续传
    win10图片打开方式里没有默认照片查看器的解决方法
    使用C#的HttpWebRequest模拟登陆网站
    在Raid模式下装Win10找不到固态硬盘怎么办
    C# String 前面不足位数补零的方法
    [SQL Server]无法创建 SSIS 运行时对象,请验证 DTS.dll 是否可用及是否已注册
    HTTPS协议说明
    技术晨读_20160217
    技术晨读_20160215
    fastcgi安装
  • 原文地址:https://www.cnblogs.com/NuoCarter/p/15261766.html
Copyright © 2020-2023  润新知