【 Educational Codeforces Round 72 - E. Sum Queries? 】 拆位+线段树

题目链接
http://codeforces.com/contest/1217/problem/E
题意
定义一个不平衡的multiset为集合中有某两个元素的十进制表示在某一位均有不为0。
现在给出一个数组,每次单点修改一个值,区间查询这个区间所有的数能组成的元素和最小的不平衡的multiset。
1 n 2 1 0 5 1 \leq n \leq 2*10^5
1 m 2 1 0 5 1 \leq m \leq 2*10^5
做法
很显然最终的不平衡multiset只可能有两个数,因为只要有两个数在某一位上都有值,这个multiset就是不平衡的,而且要求和最小,所以最终一定只有两个数字,那么我们只需要把每一位拆分开,建立十棵线段树,每一个线段树存储这一位有值的所有数,如果这一位没有值,那么该位置存储inf。线段树上的每个节点存储当前区间内最小的两个元素。单点修改的时候如果数字某一位为0,则把对应位的线段树上这个位置改为inf,否则改为当前要修改的数字。区间查询只需要对于十棵线段树分别查询,返回区间内最小的两个值,如果次小值为inf则说明当前区间不存在两个数在这一位上都非0,则不统计进答案,最后对每组的和取min即可。
例如样例
4 5
300 10001 20 20
2 1 3
1 1 310
2 1 3
2 3 3
2 3 4
首先构造五棵线段树。
数组分别为
第一棵: inf 10001 inf inf
第二棵: inf inf 20 20
第三棵: 300 inf inf inf
第四棵: inf inf inf inf
第五棵: inf 10001 inf inf
第一次对于每棵树区间[1,3]查询的结果分别为:(10001,inf),(20,inf),(300,inf),(inf,inf),(10001,inf),故答案为-1
之后单点更新,对于每棵树分别更新,更新之后的数组为:
第一棵: inf 10001 inf inf
第二棵: 310 inf 20 20
第三棵: 300 inf inf inf
第四棵: inf inf inf inf
第五棵: inf 10001 inf inf
第二次对于每棵树区间[1,3]查询的结果分别为:(10001,inf),(20,310),(300,inf),(inf,inf),(10001,inf),故答案为330
第三次对于每棵树区间[3,3]查询的结果分别为:(inf,inf),(20,inf),(inf,inf),(inf,inf),(inf,inf),故答案为-1
第四次对于每棵树区间[3,4]查询的结果分别为:(inf,inf),(20,20),(inf,inf),(inf,inf),(inf,inf),故答案为40

由于时间只有2s,拆位之后复杂度*10,有点卡时间,所以加了读入挂。
代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<map>
#include<vector>
#include<set>
#include<queue>
#include<time.h>
#include<math.h>
using namespace std;
 
#define ok cout<<"OK"<<endl;
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define dbg2(x1,x2) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<endl;
#define dbg3(x1,x2,x3) cout<<#x1<<" = "<<x1<<" "<<#x2<<" = "<<x2<<" "<<#x3<<" = "<<x3<<endl;
#define print(a,n) for(int i=1;i<=n;i++) cout<<a[i]<<" ";cout<<endl;
#define pb push_back
#define Fi first
#define Se second
#define ll long long
#define ull unsigned long long
#define pii pair<int,int>
#define pil pair<int,ll>
#define pll pair<ll,ll>
 
const double eps = 1e-8;
const double PI = acos(-1.0);
const int Mod = 1000000007;
const int INF = 0x3f3f3f3f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const int maxn = 2e5+10;
ll pw[20];
namespace fastIO
{
    #define BUF_SIZE 100000
    #define OUT_SIZE 100000
    bool IOerror=0;
    inline char nc()
    {
        static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
        if (p1==pend)
        {
            p1=buf;
            pend=buf+fread(buf,1,BUF_SIZE,stdin);
            if (pend==p1)
            {
                IOerror=1;
                return -1;
            }
        }
        return *p1++;
    }
    inline bool blank(char ch)
    {
        return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';
    }
    inline void read(int &x)
    {
        bool sign=0;
        char ch=nc();
        x=0;
        for (; blank(ch); ch=nc());
        if (IOerror)return;
        if (ch=='-')sign=1,ch=nc();
        for (; ch>='0'&&ch<='9'; ch=nc())x=x*10+ch-'0';
        if (sign)x=-x;
    }
    #undef OUT_SIZE
    #undef BUF_SIZE
};
using namespace fastIO;
 
struct T
{
    int l,r,mid;
    int mn,mn2;
}tree[11][maxn<<2];
int a[maxn];
int tt[5];
void up(int flag,int rt)
{
    int cnt=0;
    tt[++cnt] = tree[flag][rt<<1].mn;
    tt[++cnt] = tree[flag][rt<<1].mn2;
    tt[++cnt] = tree[flag][rt<<1|1].mn;
    tt[++cnt] = tree[flag][rt<<1|1].mn2;
    sort(tt+1,tt+1+cnt);
    tree[flag][rt].mn=tt[1];
    tree[flag][rt].mn2=tt[2];
    return ;
}
void build(int flag,int rt,int l,int r)
{
    tree[flag][rt].l=l;
    tree[flag][rt].r=r;
    if(l==r)
    {
        int tt=a[l]/pw[flag];
        if(tt%10==0)
        {
            tree[flag][rt].mn = INF;
            tree[flag][rt].mn2 = INF;
        }
        else
        {
            tree[flag][rt].mn = a[l];
            tree[flag][rt].mn2 = INF;
        }
        return ;
    }
    int mid=tree[flag][rt].mid=l+r>>1;
    build(flag,rt<<1,l,mid);
    build(flag,rt<<1|1,mid+1,r);
    up(flag,rt);
    return ;
}
void update(int flag,int rt,int pos,int val)
{
    if(tree[flag][rt].l==tree[flag][rt].r)
    {
        tree[flag][rt].mn = val;
        tree[flag][rt].mn2 = INF;
        return ;
    }
    if(pos<=tree[flag][rt].mid) update(flag,rt<<1,pos,val);
    else update(flag,rt<<1|1,pos,val);
    up(flag,rt);
}
pii query(int flag,int rt,int l,int r)
{
    if(tree[flag][rt].l>r&&tree[flag][rt].r<l) return pii(INF,INF);
    if(tree[flag][rt].l>=l&&tree[flag][rt].r<=r)
    {
        return pii(tree[flag][rt].mn,tree[flag][rt].mn2);
    }
    pii ans=pii(INF,INF);
    if(tree[flag][rt].mid>=l)
    {
        pii tp = query(flag,rt<<1,l,r);
        ans = tp;
    }
    if(tree[flag][rt].mid<r)
    {
        pii tp = query(flag,rt<<1|1,l,r);
        int cnt=0;
        tt[++cnt] = tp.Fi;
        tt[++cnt] = tp.Se;
        tt[++cnt] = ans.Fi;
        tt[++cnt] = ans.Se;
        sort(tt+1,tt+1+cnt);
        ans.Fi=tt[1];
        ans.Se=tt[2];
    }
    return ans;
}
int main()
{
    int n,m;
    read(n);
    read(m);
    for(int i=1;i<=n;i++) read(a[i]);
    pw[1]=1;
    for(int i=2;i<=10;i++) pw[i]=pw[i-1]*10;
    for(int i=1;i<=10;i++) build(i,1,1,n);
    while(m--)
    {
        int op,x,y;
        read(op);
        read(x);
        read(y);
        if(op==1)
        {
            for(int i=1;i<=10;i++)
            {
                int tt=y/pw[i];
                if(tt%10!=0) update(i,1,x,y);
                else update(i,1,x,INF);
            }
        }
        else
        {
            long long ans=LL_INF;
            for(int i=1;i<=10;i++)
            {
                pii tt = query(i,1,x,y);
                if(tt.Fi==INF||tt.Se==INF) continue;
                else ans=min(ans,(long long )tt.Fi+tt.Se);
            }
            if(ans==LL_INF) printf("-1\n");
            else printf("%lld\n",ans);
        }
    }
    return 0;
}
发布了299 篇原创文章 · 获赞 117 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/qq_38891827/article/details/100573589
今日推荐