1. 程式人生 > >洛谷 P4145 上帝造題的七分鐘2 / 花神遊歷各國

洛谷 P4145 上帝造題的七分鐘2 / 花神遊歷各國

pan www 復雜 是否 https math def con 代碼

洛谷

這題就是區間開根號,區間求和。我們可以分塊做。

我們記布爾數組vis[i]表示第i塊中元素是否全部為1。

因為顯然當一個塊中元素全部為1時,並不需要對它進行根號操作。

我們每個塊暴力開根號,因為數字最大\(2^31\),所以最多每個數字開幾次根號,所以時間復雜度很低。

記錄sum[i]表示第i塊的總和,所以我們得到這樣的算法:

當出現修改操作時,我們暴力修改,如果vis[i]為真,則不對該塊進行操作。

而出現查詢操作時,直接對正常操作再輸出即可。

代碼略醜:

#include <bits/stdc++.h>
#define _ putchar('\n')
using namespace std;
typedef int _int;
#define int long long

const int N=100010;
bool vis[N];
int n,m,a[N],len,num;
int pos[N],sum[N],ll[N],rr[N];

inline void read(int &aa)
{
    aa=0;char c=getchar();
    for (;c>'9'||c<'0';c=getchar());
    for (;c>='0'&&c<='9';c=getchar())
        aa=(aa<<3)+(aa<<1)+(c^48);
}

char buffer[N],*S,*T;
inline char Get_Char()
{
    if (S==T) {
        T=(S=buffer)+fread(buffer,1,N,stdin);
        if (S==T) return EOF;
    }
    return *S++;
}

int Get_Int()
{
    char c;
    int re=0;
    for (c=Get_Char();c<'0'||c>'9';c=Get_Char());
    while (c>='0'&&c<='9')
           re=(re<<1)+(re<<3)+(c-'0'),c=Get_Char();
    return re;
}

void print(int x)
{
    if (x>9) print(x/10);putchar(x%10^48);
}

void build()
{
    len=sqrt(n);
    num=n/len;if (n%len) ++num;
    for (int i=1;i<=num;++i)
        ll[i]=(i-1)*len+1,rr[i]=i*len;
    rr[num]=n;
    for (int i=1;i<=num;++i)
        for (int j=ll[i];j<=rr[i];++j)
            sum[i]+=a[j];
    for (int i=1;i<=n;++i)
        pos[i]=(i-1)/len+1;
}

int ask(int l,int r)
{
    int ans=0;
    if (pos[l]==pos[r]) {
        for (int i=l;i<=r;++i)
            ans+=a[i];
        return ans;
    }
    for (int i=l;i<=rr[pos[l]];++i)
        ans+=a[i];
    for (int i=pos[l]+1;i<pos[r];++i)
        ans+=sum[i];
    for (int i=ll[pos[r]];i<=r;++i)
        ans+=a[i];
    return ans;
}

void change(int l,int r)
{
    if (pos[l]==pos[r]) {
        if (vis[pos[l]]) return;
        for (int i=l;i<=r;++i) {
            sum[pos[l]]-=a[i];
            a[i]=sqrt(a[i]);
            sum[pos[l]]+=a[i];
        }
        vis[pos[l]]=1;
        for (int i=ll[pos[l]];i<=rr[pos[l]];++i)
            if (a[i]>1) {vis[pos[l]]=0;break;}
        return;
    }
    if (!vis[pos[l]]) {
        for (int i=l;i<=rr[pos[l]];++i) {
            sum[pos[l]]-=a[i];
            a[i]=sqrt(a[i]);
            sum[pos[l]]+=a[i];
        }
        vis[pos[l]]=1;
        for (int i=ll[pos[l]];i<=rr[pos[l]];++i)
            if (a[i]>1) {vis[pos[l]]=0;break;}
    }
    if (!vis[pos[r]]) {
        for (int i=ll[pos[r]];i<=r;++i) {
            sum[pos[r]]-=a[i];
            a[i]=sqrt(a[i]);
            sum[pos[r]]+=a[i];
        }
        vis[pos[r]]=1;
        for (int i=ll[pos[r]];i<=rr[pos[r]];++i)
            if (a[i]>1) {vis[pos[r]]=0;break;}
    }
    for (int i=pos[l]+1;i<pos[r];++i) {
        if (vis[i]) continue;
        for (int j=ll[i];j<=rr[i];++j) {
            sum[i]-=a[j];
            a[j]=sqrt(a[j]);
            sum[i]+=a[j];
        }
        vis[i]=1;
        for (int j=ll[i];j<=rr[i];++j)
            if (a[j]>1) {vis[i]=0;break;}
    }
}

_int main()
{
    n=Get_Int();
    for (int i=1;i<=n;++i) a[i]=Get_Int();
    build();
    m=Get_Int();
    int opt,l,r;
    while (m--) {
        opt=Get_Int(),l=Get_Int(),r=Get_Int();
        if (l>r) swap(l,r);
        if (opt) print(ask(l,r)),_;
        else change(l,r);
    }
    return 0;
}

洛谷 P4145 上帝造題的七分鐘2 / 花神遊歷各國