1. 程式人生 > >洛谷P4145上帝造題的七分鐘——區間修改

洛谷P4145上帝造題的七分鐘——區間修改

for none upd include sqrt uil display 代碼 ios

題目:https://www.luogu.org/problemnew/show/P4145

區間開平方,可以發現其實開幾次就變成1,不需要開了,所以標記一下,每次只去開需要開的地方;

原來寫的並查集跳過1或0,然而WA...

(如果a數組<原數組>開int會RE!)

改成線段樹,本來想著是這一段區間和只要小於等於其長度就可以跳過了,然而仔細想想完全不是,應為可能有多個0什麽的;

所以直接開bool數組標記一下就好了;

不需要pushdown,直接去修改或是跳過。

並查集:

技術分享圖片
#include<iostream>
#include<cstdio>
#include<cmath>
using
namespace std; typedef long long ll; int const MAXN=100005; int n,m,a[MAXN],fa[MAXN]; ll f[MAXN]; int find(int x) { if(x==fa[x])return x; return fa[x]=find(fa[x]); } void add(int x,ll y) { for(;x<=n;x+=(x&-x)) f[x]+=y; } void update(int x) { int tmp=a[x]; a[x]=sqrt(a[x]);
if(a[x]==1||a[x]==0)fa[x]=find(x+1); add(x,a[x]-tmp); // for(;x<=n;x+=(x&-x)) // f[x]-=tmp,f[x]+=a[x]; } ll query(int x) { // for(int i=1;i<=n;i++) // printf("%d ",a[i]); // printf("\n"); ll sum=0; for(;x;x-=(x&-x)) sum+=f[x]; return sum; } int main() { scanf(
"%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); fa[i]=i; add(i,a[i]); } // for(int i=1;i<=n;i++) // printf("%lld ",f[i]); // printf("\n"); fa[n+1]=n+1; scanf("%d",&m); while(m--) { int t,l,r; scanf("%d%d%d",&t,&l,&r); if(l>r)swap(l,r); if(t==0) { int x=find(l); while(x<=r) { update(x); x=find(x+1); // cout<<x<<endl; } } if(t==1) { ll s1=0,s2=0; if(l-1)s1=query(l-1); s2=query(r); // printf("s1=%lld s2=%lld\n",s1,s2); printf("%lld\n",s2-s1); } } return 0; }

代碼如下:

#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
int const MAXN=100005;
int n,m;
ll tr[MAXN<<2],a[MAXN];
bool tg[MAXN<<2];
void pushup(int nw)
{
    tr[nw]=tr[nw<<1]+tr[nw<<1|1];
    tg[nw]=(tg[nw<<1]&&tg[nw<<1|1]);
}
//void pushdown(int l,int r,int nw)
//{
//    if(l==r)
//    {
//        tr[nw]=sqrt(tr[nw]);
//        return;
//    }
//    while(lz[nw])
//    {
//        if(tr[nw]<=r-l+1)
//        {
//            lz[nw]=0;
//            break;
//        }
//        int mid=((l+r)>>1);
//        if(tr[nw<<1]>mid-l+1)pushdown(l,mid,nw<<1);
//        if(tr[nw<<1|1]>r-mid)pushdown(mid+1,r,nw<<1|1);
//        pushup(nw);
//        lz[nw]--;
//    }
//}
void update(int l,int r,int L,int R,int nw)
{
    if(tg[nw])return;
    if(l==r)
    {
        tr[nw]=(ll)sqrt(tr[nw]);
        if(tr[nw]==1||tr[nw]==0)tg[nw]=1;
        return;
    }
    int mid=((l+r)>>1);
    if(mid>=L)update(l,mid,L,R,nw<<1);
    if(mid<R)update(mid+1,r,L,R,nw<<1|1);
    pushup(nw);
}
ll query(int l,int r,int L,int R,int nw)
{
//    for(int i=1;i<=n;i++)
//        printf("%d ",a[i]);
//    printf("\n");
    ll sum=0;
    if(l>=L&&r<=R)
    {
//        pushdown(l,r,nw);
        return tr[nw];
    }
    int mid=((l+r)>>1);
    if(mid>=L)sum+=query(l,mid,L,R,nw<<1);
    if(mid<R)sum+=query(mid+1,r,L,R,nw<<1|1);
    return sum;
}
void build(int l,int r,int nw)
{
    if(l==r)
    {
        tr[nw]=a[l];
        if(a[l]==1||a[l]==0)tg[nw]=1;
        return;
    }
    int mid=((l+r)>>1);
    build(l,mid,nw<<1);
    build(mid+1,r,nw<<1|1);
    pushup(nw);
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
    scanf("%d",&m);
    build(1,n,1);
    while(m--)
    {
        int d,x,y;
        scanf("%d%d%d",&d,&x,&y);
        if(x>y)swap(x,y);
        if(d==0)update(1,n,x,y,1);
        if(d==1)printf("%lld\n",query(1,n,x,y,1));
    }
    return 0;
}

洛谷P4145上帝造題的七分鐘——區間修改