• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

会点儿code

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

POJ 3419 (07.10.06月赛E题)

  【题目】

Difference Is Beautiful
Time Limit:2000MS  Memory Limit:65536K
Total Submit:222 Accepted:26

Description

Mr. Flower's business is growing much faster than originally planned. He has now become the CEO of a world-famous beef corporation. However, the boss never lives a casual life because he should take charge of the subsidiary scattered all over the world. Every year, Mr. Flower needs to analyze the performance reports of these subsidiary companies.

Mr. Flower has N companies, and he numbered them with 0 to N – 1. All of the companies will give Mr. Flower a report about the development each year. Among all of the tedious data, only one thing draws Mr. Flower's attention – the turnover. Turnover of a company can be represented as an integer Pi: positive one represents the amount of profit-making while negative for loss-making.

In fact, Mr. Flower will not be angry with the companies running under deficit. He thinks these companies have a large room for future development. What dissatisfy him are those companies who created the same turnover. Because in his eyes, keeping more than one companies of the same turnover is not necessary.

Now we know the annual turnover of all companies (an integer sequence Pi, the ith represents the turnover of the ith company this year.). We say a number sequence is perfect if all of its numbers are different from each other. Mr. Flower wants to know the length of the longest consecutive perfect sequence in a certain interval [L, R] of the turnover sequence, can you help him?

 

 

 

 

Input

The first line of the input contains two integers N and M. N is the number of companies. M is the number of queries. (1 ≤ N, M ≤ 200000). The second line contains N integer numbers not exceeding 106 by their absolute values. The ith of them represents the turnover of the ith company this year. The following M lines contain query descriptions, each description consists of two numbers: L, R (0 ≤ L ≤ R ≤ N – 1) and represents the interval that Mr. Flower concerned.

 

 

 

 

Output

The output contains M lines. For each query, output the length of the longest consecutive perfect sequence between [L, R]  

 

 

 

 

Sample Input

9 2
2 5 4 1 2 3 6 2 4
0 8
2 6

 

 

 

 

Sample Output

6
5

 

 

 

 

Hint
The longest perfect sequence of the first query in the sample input is '5 4 1 2 3 6', so the answer for this query is 6.

 

比赛结束后才做出来,但是刚提交的时候数据还排第一,很高兴,所以把解题过程写下来:)

【题目大意】

        给出N个数,下标0~N-1,如果一段连续的数中,没有出现重复的数字,那么称这段数是PERFECT的。题目给出L和R,求[L,R]区域中最长的PERFECT序列是多长。(1 ≤ N, M ≤ 200000),L, R (0 ≤ L ≤ R ≤ N – 1)

【思路】   

        经常碰到这样的题目,query数非常大,这题对多200000,这样如果完成一次query的时间复杂度不够小就比较容易超时了。最好能尽量多做预处理以减少query时的计算量。我先计算几个数组。

profit[200001]: 直接从输入得来的N个数

perfect[200001]: perfect[k]表示以k位置为结尾的最长perfect串长度

repeat[200001]: k位置的perfect串P为[k-perfect[k]+1...k],那么下标为k-perfect[k]的数一定和P中某个数相同,repeat[k]就记录了P中和下标为k-perfect[k]的数相同的数的下标,如:

1,3,4,5,3,2

位置5的数为2,以2为结尾的perfect串为4,5,3,2,其中因为3和下标2的数重复所以perfect串只能这么长。perfect[5] = 4, repeat[5] = 4(profit[4]=3)。计算perfect[]和repeat[]的过程直接看注释吧:)

 

【代码和注释】

// 2759938 caogtaa 3419 Accepted 4412K 716MS C++ 1087B 2007-10-06 15:48:49 

#include <stdio.h>

#define Appear(x) \
       app[x+1000000]

bool app[2000001];
int repeat[200001];              // 以k为结尾的串中,出现重复数字的位置
int perfect[200001];              // 以k为结尾的perfect串长度
int profit[200001];              // 第k个公司的营业额

inline int mmax(int a, int b) {
       return a>b?a:b;
}

inline int mmin(int a, int b) {
       return a<b?a:b;
}

int main() {
       int N, M;
       int L, R;
       int i, k;
       scanf("%d %d", &N, &M);
       for(i=0; i<N; i++) {
              scanf("%d", profit+i);
       }

       // 约定Pk为以k为结尾的最长perfect串
       // 当前perfect串中出现的数,在app[]中对应位置为true
       perfect[0] = 1;
       repeat[0] = 0;
       Appear(profit[0]) = true;

       for(k=1; k<N; k++) {
              // 如果第k个数在Pk-1中未出现,将第k个数加入Pk-1仍然是个perfect串,那么|Pk| = |Pk-1|+1
              if( !Appear(profit[k]) ) {
                     Appear(profit[k]) = true;
                     perfect[k] = perfect[k-1]+1;
                     repeat[k] = repeat[k-1];       // repeat值和Pk-1相同
              }
              // 否则,从Pk-1开头开始找,一直找到和第k个数相同的那个数,截掉前面的那一段
              else {
                     i = k-perfect[k-1];
                     while( profit[i] != profit[k] ) {
                            Appear(profit[i]) = false;
                            i ++;
                     }
                     perfect[k] = k-i;                     // 新的串长度
                     repeat[k] = k;                            // repeat值为自己
              }
       }

       int ret;
       for(k=0; k<M; k++) {
              ret = 0;
              scanf("%d %d", &L, &R);
              while( 1 ) {
                     // 结果大于当前范围,可提前退出
                     if( R-L+1 <= ret ) {
                            break;
                     }
                     ret = mmax(ret, mmin(perfect[R], R-L+1));

                     // |P(repeat[R])| < |P(repeat[R]+1)| < ... < |P(R)|, 所以直接跳到P(repeat[R]-1)处
                     R = repeat[R]-1;
              }
              printf("%d\n", ret);
       }

       return 1;
}

posted on 2007-10-06 17:21  曹某  阅读(401)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3