0

だから私は再び助けが必要です.私は最近codechefで中レベルの問題を始めたので、TLEをかなり多く受けています.

したがって、基本的に問題は、質問で指定された複数の最大範囲クエリの合計を見つけることです。最初の範囲が指定され、問題で指定された式によって次の値が計算されます。

この問題を解決するためにセグメント ツリーを使用しましたが、いくつかのサブタスクで TLE を取得し続けています。このコードの最適化を手伝ってください。

問題のリンク - https://www.codechef.com/problems/FRMQ

//solved using segment tree
#include <stdio.h>
#define gc getchar_unlocked
inline int read_int()  //fast input function 
{
    char c = gc();
    while(c<'0' || c>'9') 
        c = gc();
    int ret = 0;
    while(c>='0' && c<='9') 
    {
        ret = 10 * ret + c - '0';
        c = gc();
    }
    return ret;
}
int min(int a,int b)
{
    return (a<b?a:b);
}
int max(int a,int b)
{
    return (a>b?a:b);
}
void construct(int a[],int tree[],int low,int high,int pos)  //constructs 
{                                          //the segment tree by recursion
    if(low==high)
    {
        tree[pos]=a[low];
        return;
    }
    int mid=(low+high)>>1;
    construct(a,tree,low,mid,(pos<<1)+1);
    construct(a,tree,mid+1,high,(pos<<1)+2);
    tree[pos]=max(tree[(pos<<1)+1],tree[(pos<<1)+2]);
}
int query(int tree[],int qlow,int qhigh,int low,int high,int pos)
{   //function finds the maximum value using the 3 cases
    if(qlow<=low && qhigh>=high)
        return tree[pos];            //total overlap
    if(qlow>high || qhigh<low)
        return -1;                   //no overlap
    int mid=(low+high)>>1;           //else partial overlap
    return max(query(tree,qlow,qhigh,low,mid,(pos<<1)+1),query(tree,qlow,qhigh,mid+1,high,(pos<<1)+2));
}
int main()
{
    int n,m,i,temp,x,y,ql,qh;
    long long int sum;
    n=read_int();
    int a[n];
    for(i=0;i<n;i++)
        a[i]=read_int();
    i=1;
    while(temp<n)       //find size of tree
    {
        temp=1<<i;
        i++;
    }
    int size=(temp<<1)-1;
    int tree[size];
    construct(a,tree,0,n-1,0);
    m=read_int();
    x=read_int();
    y=read_int();
    sum=0;
    for(i=0;i<m;i++)
    {
        ql=min(x,y);
        qh=max(x,y);
        sum+=query(tree,ql,qh,0,n-1,0);
        x=(x+7)%(n-1);     //formula to generate the range of query
        y=(y+11)%n;
    }
    printf("%lld",sum);
    return 0;
}
4

2 に答える 2

0

そうですね、100点取るにはスパーステーブルを使う必要があると思います。

コードを最適化しようとしましたhttps://www.codechef.com/viewsolution/7535957 (実行時間は 0.11 秒から 0.06 秒に短縮されました) が、サブタスク 3 を渡すにはまだ十分ではありません..

于 2015-07-24T15:01:36.507 に答える
0

いくつかのメモ:

  1. 高速 IO ルーチンを使用しているのは素晴らしいことです。
  2. モジュロ演算は非常に遅いため、絶対に使用しないでください。剰余を計算するには、数値が N 未満になるまで単純に N を減算します。これにより、はるかに高速に動作します。
  3. あなたのアルゴリズムは O((M+N) * log N) 時間で動作しますが、これは最適ではありません。静的 RMQ 問題の場合は、スパース テーブルを使用する方が適切で、はるかに簡単です。O(N log N) のスペースと O(M + N log N) の時間が必要です。
于 2015-07-18T18:22:14.693 に答える