分块大法好

用分快来水“xjr考考你数据结构”真是再爽不过了

xjr考考你数据结构一:虽然有点慢(6724ms)

#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
    char ch=getchar();int sig=1,x=0;
    while(!isdigit(ch)) {if(ch=='-') sig=-1;ch=getchar();}
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    return x*sig;
}
const int maxn=1000010;
const int INF=1000000000;
int n,SIZE,A[maxn];
int bl[maxn],st[maxn],en[maxn];
int maxv[maxn],minv[maxn],sumv[maxn];
void recal(int x)
{
    maxv[x]=-INF;minv[x]=INF;sumv[x]=0;
    for(int i=st[x];i<=en[x];i++)
    {
        maxv[x]=max(maxv[x],A[i]);
        minv[x]=min(minv[x],A[i]);
        sumv[x]+=A[i];
    }
}
int main()
{
    n=read();SIZE=(int)sqrt(n);
    for(int i=1;i<=n;i++)
    {
        A[i]=read();
        bl[i]=(i-1)/SIZE+1;
        en[bl[i]]=i;
        if(!st[bl[i]]) st[bl[i]]=i;
    }
    for(int i=1;i<=bl[n];i++) recal(i);
    int q=read(),l,r,x,v;
    while(q--)
    {
        char tp=getchar();
        while(!isalpha(tp)) tp=getchar();
        if(tp=='Q')
        {
            l=read();r=read();
            int mx=-INF,mn=INF,sum=0;
            if(bl[l]==bl[r]) for(int i=l;i<=r;i++) mx=max(mx,A[i]),mn=min(mn,A[i]),sum+=A[i];
            else
            {
                for(int i=l;i<=en[bl[l]];i++) mx=max(mx,A[i]),mn=min(mn,A[i]),sum+=A[i];
                for(int i=st[bl[r]];i<=r;i++) mx=max(mx,A[i]),mn=min(mn,A[i]),sum+=A[i];
                for(int i=bl[l]+1;i<bl[r];i++) mx=max(mx,maxv[i]),mn=min(mn,minv[i]),sum+=sumv[i];
            }
            printf("MaxNum: %d, MinNum: %d, Sum: %d\n",mx,mn,sum);
        }
        else 
        {
            x=read();v=read();
            A[x]=v;recal(bl[x]);
        }
    }
    return 0;
}
View Code

xjr考考你数据结构二:加个add标记(1342ms)

#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
    char ch=getchar();int sig=1,x=0;
    while(!isdigit(ch)) {if(ch=='-') sig=-1;ch=getchar();}
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    return x*sig;
}
const int maxn=100010;
const int INF=1000000000;
int n,SIZE;
int bl[maxn],st[maxn],en[maxn];
long long A[maxn],maxv[maxn],minv[maxn],sumv[maxn],add[maxn];
void recal(int x)
{
    maxv[x]=-INF;minv[x]=INF;sumv[x]=0;
    for(int i=st[x];i<=en[x];i++)
    {
        maxv[x]=max(maxv[x],A[i]);
        minv[x]=min(minv[x],A[i]);
        sumv[x]+=A[i];
    }
}
int main()
{
    n=read();SIZE=(int)sqrt(n);
    for(int i=1;i<=n;i++)
    {
        A[i]=read();
        bl[i]=(i-1)/SIZE+1;
        en[bl[i]]=i;
        if(!st[bl[i]]) st[bl[i]]=i;
    }
    for(int i=1;i<=bl[n];i++) recal(i);
    int q=read(),l,r,v;
    while(q--)
    {
        char tp=getchar();
        while(!isalpha(tp)) tp=getchar();
        if(tp=='Q')
        {
            l=read();r=read();if(l>r) swap(l,r);
            long long mx=-INF,mn=INF,sum=0;
            if(bl[l]==bl[r]) for(int i=l;i<=r;i++) mx=max(mx,A[i]+add[bl[r]]),mn=min(mn,A[i]+add[bl[r]]),sum+=A[i]+add[bl[r]];
            else
            {
                for(int i=l;i<=en[bl[l]];i++) mx=max(mx,A[i]+add[bl[l]]),mn=min(mn,A[i]+add[bl[l]]),sum+=A[i]+add[bl[l]];
                for(int i=st[bl[r]];i<=r;i++) mx=max(mx,A[i]+add[bl[r]]),mn=min(mn,A[i]+add[bl[r]]),sum+=A[i]+add[bl[r]];
                for(int i=bl[l]+1;i<bl[r];i++) mx=max(mx,maxv[i]+add[i]),mn=min(mn,minv[i]+add[i]),sum+=sumv[i]+add[i]*(en[i]-st[i]+1);
            }
            printf("MaxNum: %lld, MinNum: %lld, Sum: %lld\n",mx,mn,sum);
        }
        else 
        {
            l=read();r=read();v=read();if(l>r) swap(l,r);
            if(bl[l]==bl[r])
            {
                for(int i=l;i<=r;i++) A[i]+=v;
                recal(bl[l]);
            }
            else
            {
                for(int i=l;i<=en[bl[l]];i++) A[i]+=v;
                for(int i=st[bl[r]];i<=r;i++) A[i]+=v;
                for(int i=bl[l]+1;i<bl[r];i++) add[i]+=v;
                recal(bl[l]);recal(bl[r]);
            }
        }
    }
    return 0;
}
View Code

xjr考考你数据结构三:换成set标记(偷懒将维护信息和传递信息写一块了),这时间(999ms)

#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
    char ch=getchar();int sig=1,x=0;
    while(!isdigit(ch)) {if(ch=='-') sig=-1;ch=getchar();}
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    return x*sig;
}
const int maxn=100010;
const int INF=1000000000;
int n,SIZE;
int bl[maxn],st[maxn],en[maxn];
long long A[maxn],maxv[maxn],minv[maxn],sumv[maxn],set[maxn];
void recal(int x)
{
    if(set[x]) for(int i=st[x];i<=en[x];i++) A[i]=set[x];
    maxv[x]=-INF;minv[x]=INF;sumv[x]=0;
    for(int i=st[x];i<=en[x];i++)
    {
        maxv[x]=max(maxv[x],A[i]);
        minv[x]=min(minv[x],A[i]);
        sumv[x]+=A[i];
    }
    set[x]=0;
}
int main()
{
    n=read();SIZE=(int)sqrt(n);
    for(int i=1;i<=n;i++)
    {
        A[i]=read();
        bl[i]=(i-1)/SIZE+1;
        en[bl[i]]=i;
        if(!st[bl[i]]) st[bl[i]]=i;
    }
    for(int i=1;i<=bl[n];i++) recal(i);
    int q=read(),l,r,v;
    while(q--)
    {
        char tp=getchar();
        while(!isalpha(tp)) tp=getchar();
        if(tp=='Q')
        {
            l=read();r=read();if(l>r) swap(l,r);
            long long mx=-INF,mn=INF,sum=0;
            if(bl[l]==bl[r]) 
            {
                if(set[bl[l]]) mx=mn=set[bl[l]],sum=set[bl[l]]*(r-l+1);
                else for(int i=l;i<=r;i++) mx=max(mx,A[i]),mn=min(mn,A[i]),sum+=A[i];
            }
            else
            {
                if(set[bl[l]]) mx=mn=set[bl[l]],sum=set[bl[l]]*(en[bl[l]]-l+1);
                else for(int i=l;i<=en[bl[l]];i++) mx=max(mx,A[i]),mn=min(mn,A[i]),sum+=A[i];
                if(set[bl[r]]) mx=max(mx,set[bl[r]]),mn=min(mn,set[bl[r]]),sum+=set[bl[r]]*(r-st[bl[r]]+1);
                else for(int i=st[bl[r]];i<=r;i++) mx=max(mx,A[i]),mn=min(mn,A[i]),sum+=A[i];
                for(int i=bl[l]+1;i<bl[r];i++) mx=max(mx,maxv[i]),mn=min(mn,minv[i]),sum+=sumv[i];
            }
            printf("MaxNum: %lld, MinNum: %lld, Sum: %lld\n",mx,mn,sum);
        }
        else 
        {
            l=read();r=read();v=read();if(l>r) swap(l,r);
            if(bl[l]==bl[r])
            {
                recal(bl[l]);
                for(int i=l;i<=r;i++) A[i]=v;
                recal(bl[l]);
            }
            else
            {
                recal(bl[l]);recal(bl[r]);
                for(int i=l;i<=en[bl[l]];i++) A[i]=v;
                for(int i=st[bl[r]];i<=r;i++) A[i]=v;
                for(int i=bl[l]+1;i<bl[r];i++) set[i]=v,maxv[i]=minv[i]=set[i],sumv[i]=set[i]*(en[i]-st[i]+1);
                recal(bl[l]);recal(bl[r]);
            }
        }
    }
    return 0;
}
View Code

 最后是我的WZJ的数据结构(十),写的我已然TAT。(1810ms)

#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
inline int read()
{
    char ch=getchar();int sig=1,x=0;
    while(!isdigit(ch)) {if(ch=='-') sig=-1;ch=getchar();}
    while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
    return x*sig;
}
const int maxn=100010;
const int INF=1000000000;
int n,SIZE;
int bl[maxn],st[maxn],en[maxn];
long long A[maxn],maxv[maxn],minv[maxn],sumv[maxn],set[maxn],add[maxn];
void pushdown(int x)
{
    if(set[x]) for(int i=st[x];i<=en[x];i++) A[i]=set[x]+add[x];
    else for(int i=st[x];i<=en[x];i++) A[i]+=add[x];
    add[x]=set[x]=0;
}
void recal(int x)
{
    maxv[x]=-INF;minv[x]=INF;sumv[x]=0;
    for(int i=st[x];i<=en[x];i++)
    {
        maxv[x]=max(maxv[x],A[i]);
        minv[x]=min(minv[x],A[i]);
        sumv[x]+=A[i];
    }
}
int main()
{
    n=read();int q=read();SIZE=(int)sqrt(n);
    for(int i=1;i<=n;i++)
    {
        A[i]=read();
        bl[i]=(i-1)/SIZE+1;
        en[bl[i]]=i;
        if(!st[bl[i]]) st[bl[i]]=i;
    }
    for(int i=1;i<=bl[n];i++) recal(i);
    int l,r,v;
    while(q--)
    {
        int t=read(); 
        if(t==2)
        {
            l=read();r=read();if(l>r) swap(l,r);
            long long mx=-INF,mn=INF,sum=0;
            if(bl[l]==bl[r]) 
            {
                if(set[bl[l]]) mx=mn=set[bl[l]],sum=set[bl[l]]*(r-l+1);
                else for(int i=l;i<=r;i++) mx=max(mx,A[i]),mn=min(mn,A[i]),sum+=A[i];
                mx+=add[bl[l]];mn+=add[bl[l]];sum+=add[bl[l]]*(r-l+1);
            }
            else
            {
                if(set[bl[l]]) mx=mn=set[bl[l]]+add[bl[l]],sum=(set[bl[l]]+add[bl[l]])*(en[bl[l]]-l+1);
                else for(int i=l;i<=en[bl[l]];i++) mx=max(mx,A[i]+add[bl[l]]),mn=min(mn,A[i]+add[bl[l]]),sum+=A[i]+add[bl[l]];
                if(set[bl[r]]) mx=max(mx,set[bl[r]]+add[bl[r]]),mn=min(mn,set[bl[r]]+add[bl[r]]),sum+=(set[bl[r]]+add[bl[r]])*(r-st[bl[r]]+1);
                else for(int i=st[bl[r]];i<=r;i++) mx=max(mx,A[i]+add[bl[r]]),mn=min(mn,A[i]+add[bl[r]]),sum+=A[i]+add[bl[r]];
                for(int i=bl[l]+1;i<bl[r];i++) mx=max(mx,maxv[i]),mn=min(mn,minv[i]),sum+=sumv[i];
            }
            printf("%lld %lld %lld\n",mx,mn,sum);
        }
        else 
        {
            l=read();r=read();v=read();if(l>r) swap(l,r);
            if(bl[l]==bl[r])
            {
                pushdown(bl[l]);
                if(!t) for(int i=l;i<=r;i++) A[i]=v;
                else for(int i=l;i<=r;i++) A[i]+=v;
                recal(bl[l]);
            }
            else
            {
                pushdown(bl[l]);pushdown(bl[r]);
                if(!t) for(int i=l;i<=en[bl[l]];i++) A[i]=v;
                else for(int i=l;i<=en[bl[l]];i++) A[i]+=v;
                if(!t) for(int i=st[bl[r]];i<=r;i++) A[i]=v;
                else for(int i=st[bl[r]];i<=r;i++) A[i]+=v;
                if(!t) for(int i=bl[l]+1;i<bl[r];i++) add[i]=0,set[i]=v,maxv[i]=minv[i]=set[i],sumv[i]=set[i]*(en[i]-st[i]+1);
                else for(int i=bl[l]+1;i<bl[r];i++) add[i]+=v,maxv[i]+=v,minv[i]+=v,sumv[i]+=v*(en[i]-st[i]+1);
                recal(bl[l]);recal(bl[r]);
            }
        }
    }
    return 0;
}
View Code

 

posted @ 2015-06-14 20:12  wzj_is_a_juruo  阅读(315)  评论(2编辑  收藏  举报