• 2019icpc徐州现场赛 H Yuuki and a problem (树状数组套主席树)


    题意

    2e5的数组,q个操作
    1.将(a[x])改为y
    2.求下标l到r内所有的(a[i])通过加法不能构成的最小的值

    思路

    通过二操作可以知道需要提取l到r内的值及其数量,而提取下标为l到r内的元素是一定要用主席树的
    而用树状数组套上主席树即可实现修改操作

    剩下需要解决的就是二操作:
    首先只有有至少一个1,才能构成1
    假设已经可以构成[1,x],设当前区间内值为[1,x+1]的和为sum
    那显然我们就能构成[1,sum]了,如果sum==x,那么答案就是x+1
    这个过程可以直接暴力,最坏情况下当前区间里的数是{1,2,3,5,8,13...},在第27项就到到2e5了,所以最多跑27次
    那么复杂度O((27qlog^2n))

    这题其实比较友好,不需要离散化,也不需要优化空间,赞
    比赛的时候其实也很可写,可惜

    代码

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<string>
    #include<stack>
    #include<queue>
    #include<deque>
    #include<set>
    #include<vector>
    #include<map>
    #include<functional>
        
    #define fst first
    #define sc second
    #define pb push_back
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson l,mid,root<<1
    #define rson mid+1,r,root<<1|1
    #define lc root<<1
    #define rc root<<1|1
     
    using namespace std;
     
    typedef double db;
    typedef long double ldb;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> PI;
    typedef pair<ll,ll> PLL;
    typedef pair<ll,int> PIL;
     
    const db eps = 1e-2;
    const int mod = 1e9+7;
    const int maxn = 2e5+100;
    const int maxm = maxn*150;
    const int inf = 0x3f3f3f3f;
    const db pi = acos(-1.0);
    
    
    int n,m;
    inline int read(){
        int num;
        char ch;
        while((ch=getchar())<'0' || ch>'9');
        num=ch-'0';
        while((ch=getchar())>='0' && ch<='9'){
            num=num*10+ch-'0';
        }
        return num;
    }
    struct qst{
        int op;
        int x,y;
    }prb[maxn];
    ll a[maxn];
    int totn,tot;
    int rrot[maxn];
    int ls[maxm],rs[maxm];
    ll dat[maxm];
    int root[maxn];
    inline void insert(int &now, int l, int r, int x, int val){
        if(!now)now=++tot;
        dat[now]+=val;
        if(l==r)return;
        int mid = (l+r)>>1;
        if(x<=mid)insert(ls[now],l,mid,x,val);
        else insert(rs[now],mid+1,r,x,val);
    }
    int totL,totR;
    int L[maxn],R[maxn];
    inline ll ask(int l, int r, int k){
        if(r==k){
            ll ans=0;
            for(int i = 1; i <= totL; i++)ans-=dat[L[i]];
            for(int i = 1; i <= totR; i++)ans+=dat[R[i]];
            return ans;
        }
        int mid=(l+r)>>1;
        if(k<=mid){
            for(int i = 1; i <= totL; i++)L[i]=ls[L[i]];
            for(int i = 1; i <= totR; i++)R[i]=ls[R[i]];
            return ask(l,mid,k);
        }
        else{
            ll ans = 0;
            for(int i = 1; i <= totL; i++)ans-=dat[ls[L[i]]];
            for(int i = 1; i <= totR; i++)ans+=dat[ls[R[i]]];
    
            for(int i = 1; i <= totL; i++)L[i]=rs[L[i]];
            for(int i = 1; i <= totR; i++)R[i]=rs[R[i]];
            return ans+ask(mid+1,r,k);
        }
    }
    inline int lowbit(int x){return x&-x;}
    int main() {
        int q;
        scanf("%d %d",&n, &q);
        for(int i = 1; i <= n; i++){
            a[i]=1ll*read();
        }
        totn=200000;
        for(int i = 1; i <= n; i++){
            int t = a[i];
            for(int j = i; j <= n; j+=lowbit(j)){
                insert(root[j],1,totn,t,a[i]);
            }
        }
        for(int i = 1; i <= q; i++){
            prb[i].op=read();prb[i].x=read();prb[i].y=read();
            if(prb[i].op==1){
                ll t = a[prb[i].x];
                int tt = prb[i].y;
                a[prb[i].x]=prb[i].y;
                for(int j = prb[i].x; j<=n; j+=lowbit(j)){
                    insert(root[j],1,totn,t,-t);
                    insert(root[j],1,totn,tt,tt);
                }
            }
            else{
                prb[i].x--;
    
                ll now = 1;
                ll sum = 0;
                while(1){
                    totL=totR=0;
                    for(int j = prb[i].x; j; j-=lowbit(j))L[++totL]=root[j];
                    for(int j = prb[i].y; j; j-=lowbit(j))R[++totR]=root[j];
    
                    int t = min(now,200000ll);
                    ll tmp = ask(1,totn,t);
                    if(tmp==sum){
                        printf("%lld
    ",now);
                        break;
                    }
                    sum=tmp;now=sum+1;
                }
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    理解volatile与synchronized
    实现任意两个数的互换
    增删改查+部分前段内容
    Hibernate知识点小结汇总
    Spring知识点小结(一)
    JDBC相关
    Redis工具之Jedis
    Hibernate知识点小结(四)--JPA
    Hibernate知识点小结(三)-->一对多与多对多配置
    Hibernate知识点小结(二)
  • 原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/12013960.html
Copyright © 2020-2023  润新知