bzoj4278: [ONTAK2015]Tasowanie

stl::sort实现的后缀数组,超级慢。

变量名打错好几个导致WA好几次。

http://www.lydsy.com/JudgeOnline/problem.php?id=4278

/**************************************************************

    Problem: 4278

    User: 1349367067

    Language: C++

    Result: Accepted

    Time:7900 ms

    Memory:13776 kb

****************************************************************/

#include<iostream>

#include<cstdio>

#include<cstring>

#include<algorithm>

usingnamespacestd;

intn,m,a[200011]={},b[200011]={};

intr[800011]={},num;

intSA[400011]={},RA[400011]={};

voidinit()

{

     scanf("%d",&n);

     for(inti=1;i<=n;i++) scanf("%d",&a[i]);

     scanf("%d",&m);

     for(inti=1;i<=m;i++) scanf("%d",&b[i]);

     for(inti=1;i<=n;i++) r[i]=a[i];

     for(inti=1;i<=m;i++) r[n+i+1]=b[i];

     r[n+1+m+1]=r[n+1]=1000000;

     num=n+m+2;

}

structTEM

{

       intx,y,i;

}tem[400011];

boolcmp(TEM a,TEM b)

{

     if(a.x<b.x) return1;

     if(a.x>b.x) return0;

     if(a.y<b.y) return1;

     return0;

}

voidprintff()

{

     for(inti=1;i<=num;i++)

         cout<<tem[i].x<<" "<<tem[i].y<<" "<<tem[i].i<<endl;

     cout<<"*************"<<endl;

     system("pause");

}

voidprintfff()

{

     for(inti=1;i<=num;i++)

         cout<<r[i]<<" ";

     cout<<endl<<"&&&&&&&&&&&&&"<<endl;

     system("pause");

}

boolcheck(inti)

{

     if(tem[i].x==tem[i-1].x&&tem[i].y==tem[i-1].y)

        returntrue;

     returnfalse;

}

voidsuffix_maker()

{

     intt,T;

     for(inti=1;i<=num;i++)

     {

         tem[i].x=r[i];tem[i].y=0;

         tem[i].i=i;

     }

     sort(tem+1,tem+num+1,cmp);

     //printff();

     T=0;

     for(inti=1;i<=num;i++)

     {

         if(!check(i)) T++;

         t=tem[i].i;

         r[t]=T;

     }

     //printfff();

     for(inti=1;i<=num;i=i*2)

     {

         for(intj=1;j<=num;j++)

         {

             tem[j].x=r[j];tem[j].y=r[j+i];

             tem[j].i=j;

         }

         sort(tem+1,tem+num+1,cmp);

         //printff();

         T=0;

         for(intj=1;j<=num;j++)

         {

             if(!check(j)) T++;

             t=tem[j].i;

             r[t]=T;

         }

         //printfff();

     }

}

voidwork()

{

     intl=1,R=1;

     while(!(l>n&&R>m))

     {

           //cout<<endl<<l-1<<" * "<<R-1<<endl;

           if(l>n) {printf("%d ",b[R++]);continue;}

           if(R>m) {printf("%d ",a[l++]);continue;}

           if(a[l]<b[R]) {printf("%d ",a[l++]);continue;}

           if(a[l]>b[R]) {printf("%d ",b[R++]);continue;}

           if(r[l]<r[n+R+1])

              {printf("%d ",a[l++]);continue;}

           else

              {printf("%d ",b[R++]);continue;}

     }

}

intmain()

{

    init();

    suffix_maker();

    //printfff();

    work();

    return0;

}

时间: 2024-08-02 06:59:37

bzoj4278: [ONTAK2015]Tasowanie的相关文章

【BZOJ4278】[ONTAK2015]Tasowanie 后缀数组

[BZOJ4278][ONTAK2015]Tasowanie Description 给定两个数字串A和B,通过将A和B进行二路归并得到一个新的数字串T,请找到字典序最小的T. Input 第一行包含一个正整数n(1<=n<=200000),表示A串的长度. 第二行包含n个正整数,其中第i个数表示A[i](1<=A[i]<=1000). 第三行包含一个正整数m(1<=m<=200000),表示B串的长度. 第四行包含m个正整数,其中第i个数表示B[i](1<=B[

【BZOJ-4278】Tasowanie 后缀数组 + 归并

4278: [ONTAK2015]Tasowanie Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 164  Solved: 80[Submit][Status][Discuss] Description 给定两个数字串A和B,通过将A和B进行二路归并得到一个新的数字串T,请找到字典序最小的T. Input 第一行包含一个正整数n(1<=n<=200000),表示A串的长度. 第二行包含n个正整数,其中第i个数表示A[i](1<=A[i]

●BZOJ 4278 [ONTAK2015]Tasowanie

题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4278 题解: 把两个串连接起来,用一个大数连接(必须要用大数).倍增算法求出后缀排名.然后两个指针指向A,B串,每次比较两个后缀的大小,优先取出小的那个后缀的首字母,然后对应指针向后移动一位. 代码: #include<cstdio> #include<cstring> #include<iostream> #define MAXN 450000 #define

【BZOJ4281】[ONTAK2015]Zwi?zek Harcerstwa Bajtockiego LCA

[BZOJ4281][ONTAK2015]Zwi?zek Harcerstwa Bajtockiego Description 给定一棵有n个点的无根树,相邻的点之间的距离为1,一开始你位于m点.之后你将依次收到k个指令,每个指令包含两个整数d和t,你需要沿着最短路在t步之内(包含t步)走到d点,如果不能走到,则停在最后到达的那个点.请在每个指令之后输出你所在的位置. Input 第一行包含三个正整数n,m,k(1<=m<=n<=1000000,1<=k<=1000000).

BZOJ 4245: [ONTAK2015]OR-XOR 贪心

4245: [ONTAK2015]OR-XOR Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 567  Solved: 312[Submit][Status][Discuss] Description 给定一个长度为n的序列a[1],a[2],...,a[n],请将它划分为m段连续的区间,设第i段的费用c[i]为该段内所有数字的异或和,则总费用为c[1] or c[2] or ... or c[m].请求出总费用的最小值. Input 第一行包含

【BZOJ4245】[ONTAK2015]OR-XOR 贪心

[BZOJ4245][ONTAK2015]OR-XOR Description 给定一个长度为n的序列a[1],a[2],...,a[n],请将它划分为m段连续的区间,设第i段的费用c[i]为该段内所有数字的异或和,则总费用为c[1] or c[2] or ... or c[m].请求出总费用的最小值. Input 第一行包含两个正整数n,m(1<=m<=n<=500000),分别表示序列的长度和需要划分的段数. 第一行包含n个整数,其中第i个数为a[i](0<=a[i]<=

4245: [ONTAK2015]OR-XOR

4245: [ONTAK2015]OR-XOR https://www.lydsy.com/JudgeOnline/problem.php?id=4245 1 /* 2 要求分成m份,总价值为a1|a2|a3...,总价值最小,ai为第i份的异或和. 3 4 首先预处理异或和. 5 根据贪心的思想,高位最好是0. 6 于是从高位往低位枚举,看一下每一位是否可以为0. 7 如果当前这一位可以为0,每一份的(异或和)(或)起来都是0,所以每一份异或和的这一位不能有1 8 那么一个点可以成为分割点当且

[bzoj4281][ONTAK2015]Zwi?zek Harcerstwa Bajtockiego_倍增LCA

Zwi?zek Harcerstwa Bajtockiego bzoj-4281 ONTAK-2015 题目大意:给定一棵有n个点的无根树,相邻的点之间的距离为1,一开始你位于m点.之后你将依次收到k个指令,每个指令包含两个整数d和t,你需要沿着最短路在t步之内(包含t步)走到d点,如果不能走到,则停在最后到达的那个点.请在每个指令之后输出你所在的位置. 注释:$1\le n,m,k\le 10^6$,$m\le n$. 想法: 对于每一个指令,用倍增LCA判一下能不能到达即可. Code: #

【bzoj4245】[ONTAK2015]OR-XOR

利用前缀和选m个区间等价于选m个数 从最高位开始找,如果这一位至少有m个0,则可以为0,该位为1的后面就不可以选了. 还要注意,最后一个数如果该位为1,那么这一位必须为1,然后要从62开始枚举,而不是从31 #include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> using n