CF1217E Sum Queries? (线段树)

Posted 1000suns

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF1217E Sum Queries? (线段树)相关的知识,希望对你有一定的参考价值。

完了,前几天才说 edu 的 DEF 都不会,现在打脸了吧 qwq

其实在刚说完这句话 1min 就会了 D,3min 就会了 E

发现,对于大小 \(\ge 3\) 的不平衡集合,它至少有一个大小为 \(2\) 的子集是不平衡的。

证明,发现对于大小为 \(2\) 的集合,平衡当且仅当两数的数位交为空(对于任意一位,至多一个数在这一位上不是 \(0\))。

反证一波,如果大集合没有大小为 \(2\) 的不平衡集合,那么任意两数的数位交都为空,那么大集合也是平衡的,矛盾了。

所以,只需要考虑大小为 \(2\) 的集合。

这个就能线段树简单做了,每个线段树维护 \(ans\) 表示这个区间中的答案,\(mn_i\) 表示这个区间中第 \(i\) 位有值的数的最小值。pushup 具体看代码。

时间复杂度 \(O((n+q\log n)\log a_i)\)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=200020,pw[9]=1,10,100,1000,10000,100000,1000000,10000000,100000000;
#define MP make_pair
#define PB push_back
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline ll read()
    char ch=getchar();ll x=0,f=0;
    while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return f?-x:x;

int n,m,a[maxn];
struct node
    ll ans,mn[9];
    node operator+(const node &nd)const
        node s;
        s.ans=min(ans,nd.ans);
        FOR(i,0,8) s.ans=min(s.ans,mn[i]+nd.mn[i]),s.mn[i]=min(mn[i],nd.mn[i]);
        return s;
    
seg[maxn*4];
inline int get(int x,int id)return x/pw[id]%10;
void build(int o,int l,int r)
    if(l==r)
        seg[o].ans=1e18;
        FOR(i,0,8) seg[o].mn[i]=get(a[l],i)?a[l]:1e18;
        return;
    
    int mid=(l+r)>>1;
    build(lson);build(rson);
    seg[o]=seg[o<<1]+seg[o<<1|1];

void update(int o,int l,int r,int p,int v)
    if(l==r)
        seg[o].ans=1e18;
        FOR(i,0,8) seg[o].mn[i]=get(v,i)?v:1e18;
        return;
    
    int mid=(l+r)>>1;
    if(mid>=p) update(lson,p,v);
    else update(rson,p,v);
    seg[o]=seg[o<<1]+seg[o<<1|1];

node query(int o,int l,int r,int ql,int qr)
    if(l>=ql && r<=qr) return seg[o];
    int mid=(l+r)>>1;
    if(mid<ql) return query(rson,ql,qr);
    if(mid>=qr) return query(lson,ql,qr);
    return query(lson,ql,qr)+query(rson,ql,qr);

int main()
    n=read();m=read();
    FOR(i,1,n) a[i]=read();
    build(1,1,n);
    while(m--)
        int op=read(),x=read(),y=read();
        if(op==1) update(1,1,n,x,y);
        else
            ll ans=query(1,1,n,x,y).ans;
            printf("%lld\n",ans>=2e9?-1ll:ans);
        
    

以上是关于CF1217E Sum Queries? (线段树)的主要内容,如果未能解决你的问题,请参考以下文章

CF911G Mass Change Queries (线段树区间 合并)

CF938G Shortest Path Queries (线段树分治)

CF 1093G Multidimensional Queries——线段树(消去绝对值符号)

cf375D. Tree and Queries(树上启发式合并+线段树)

CF1114F Please, another Queries on Array?(线段树,数论,欧拉函数,状态压缩)

CF 938G Shortest Path Queries