跪求卡常!

P3793 由乃救爷爷

skydogli @ 2019-05-07 14:23:31

#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define Re register
#define K (2048)
#define ULL unsigned long long
namespace GenHelper
{
    unsigned z1,z2,z3,z4,b;
    unsigned rand_()
    {
    b=((z1<<6)^z1)>>13;
    z1=((z1&4294967294U)<<18)^b;
    b=((z2<<2)^z2)>>27;
    z2=((z2&4294967288U)<<2)^b;
    b=((z3<<13)^z3)>>21;
    z3=((z3&4294967280U)<<7)^b;
    b=((z4<<3)^z4)>>12;
    z4=((z4&4294967168U)<<13)^b;
    return (z1^z2^z3^z4);
    }
}
void srand(unsigned x)
{using namespace GenHelper;
z1=x; z2=(~x)^0x233333333U; z3=x^0x1234598766U; z4=(~x)+51;}
int read()
{
    using namespace GenHelper;
    int a=rand_()&32767;
    int b=rand_()&32767;
    return a*32768+b;
}
#define MN 20000005
unsigned int st[K][MN/K+3],Log[MN],pre[MN],nex[MN],loc[MN],a[MN],s,l,r,res;
int LOG[26]={1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,32768,65536,131072,262144,524288,1048576,2097152,4194304,8388608,16777216,20000001};
ULL ans;
int n,m,T;
inline int Max(unsigned a,unsigned b){return a>b?a:b;}
inline void build(){
    for(Re int i=1;i<=n;++i)loc[i]=(i-1)/K+1;
    for(Re int i=1;i<=n;++i)
        pre[i]=(loc[i]!=loc[i-1])?a[i]:Max(pre[i-1],a[i]);
    for(Re int i=n;i>0;--i)
        nex[i]=(loc[i]!=loc[i+1])?a[i]:Max(nex[i+1],a[i]);
    for(Re int i=1;i<=T;++i)st[0][i]=pre[i*K];
    for(Re int l=1;LOG[l]<=T;++l)
        for(Re int i=1;i+LOG[l]<=T;++i)
            st[l][i]=Max(st[l-1][i],st[l-1][i+(1<<(l-1))]);
}
int vis;
inline void rmq(int l,int r){
    if(loc[l]==loc[r]){
        res=a[l];
        for(Re int i=l+1;i<=r;++i)if(res<a[i])res=a[i];
        return;
    }
    res=(nex[l]<pre[r])?pre[r]:nex[l];
    int L=loc[l]+1,R=loc[r]-1;
    if(L>R)return;
    int k=Log[R-L+1];
    if(res<st[k][L])res=st[k][L];
    if(res<st[k][R-LOG[k]+1])res=st[k][R-LOG[k]+1];
}
int main(){
    freopen("3793.in","r",stdin);
    freopen("3793.out","w",stdout);
    scanf("%d%d%u",&n,&m,&s);T=n/K+1;
    double start=clock();
    int now=0,x=1;
    while(LOG[now]<T){
        ++now;
        for(Re int i=x;i<LOG[now];++i)Log[i]=now-1;
        x=LOG[now];
    }
    srand(s);
    for(Re int i=1;i<=n;++i)a[i]=read();
    build();
    for(Re int i=1;i<=m;++i){
        Re int l=read()%n+1,r=read()%n+1;
        if(r<l)std::swap(l,r);
        rmq(l,r);
    ans+=res;
    }
    printf("%llu\n",ans);
    double endT=clock();    cout<<"take "<<(endT-start)*1000.0/CLOCKS_PER_SEC<<"ms"<<endl;
 // cout<<"VIS: "<<vis<<endl;
    return 0;
} 

by skydogli @ 2019-05-07 14:24:24

80分,可以看评测记录,本机开O2已经4100ms了,还是过不了


by skydogli @ 2019-05-07 14:28:32

打表的心都有了...


by malloc_size @ 2019-05-07 14:38:18

换其他语言

换算法?


by skydogli @ 2019-05-07 14:43:23

分块RMQ算法复杂度没问题啊...


by cosmicAC @ 2019-05-07 14:45:14

真的,本机1秒都能T,你4000ms算什么


by cosmicAC @ 2019-05-07 14:45:57

@skydogli


// Data #2 : 20000000 20000000 13249    time=1.525s
// Data #10: 20000000 20000000 14529    time=1.434s

by skydogli @ 2019-05-07 14:46:51

@SarvaTathagata 哇,那怎么办


by Ynoi @ 2019-05-07 14:50:18

@skydogli 不要用std::swap

使用 l^=r,r^=l,l^=r


by skydogli @ 2019-05-07 14:58:56

@树链剖分 谢谢,然而还是过不了


by skydogli @ 2019-05-07 14:59:58

这个程序瓶颈是在rmq部分,而且还是线性部分,用了好长时间...


| 下一页