2-1791F

发布时间 2023-11-17 18:41:04作者: xxj112

题意:

思路:首先发现对于每一个数,最多被只会被操作3次,就会变成1。可以用线段树,维护区间和,如果区间和等于区间长度,则无需操作,时间复杂度为3nlog(n);
考虑到线段树的代码太多,
也可以,现予处理出每个数的前三次操作,用树状数组,记录每个点的操作次数。
代码:

点击查看代码
#include <bits/stdc++.h>
#define int long long 
using namespace std;

const int N = 1e6 + 10;
int a[N][4],tree[N];
int n,q;
int ck(int x)
{
    int res=0;
    while(x)
    {
        res+=x%10;

        x=x/10;
    }
    return res;
}
int lowbit(int x)
{
    return x&(-x);
}

void add(int x,int k)
{
    while(x<=n)
    {
        tree[x]+=k;
        x+=lowbit(x);
    }

}


int ser(int x)//求sum 1~x
{
    int ans=0;

    while(x>0)
    {
        ans+=tree[x];

        x-=lowbit(x);
    }
    return ans;
}

void solve()
{
    cin>>n>>q;
    for(int i=0;i<=n+1;i++) tree[i]=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i][0];
        a[i][1]=ck(a[i][0]);
        a[i][2]=ck(a[i][1]);
        a[i][3]=ck(a[i][2]);
    }
    int l,r,op,x;
    for(int i=1;i<=q;i++)
    {
        cin>>op;
        if(op==1)
        {
            cin>>l>>r;
            add(l,1);
         
            add(r+1,-1);
        }
        else
        {
            cin>>x;
            int w=ser(x);
            if(x-1>0) w-ser(x-1);
            w=min(w,3ll);
           // cout<<w<<"\n";
            cout<<a[x][w]<<"\n";
        }
    }
   
}
signed main() {
    cin.tie(nullptr)->sync_with_stdio(false);
    int t=1;
    cin>>t;
    while(t--)
    {
        solve();
    }
    return 0 ^ 0;
}