## Difference Is Beautiful

Time Limit: 5000MS Memory Limit: 65536K
Total Submissions: 2141 Accepted: 672
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.
Source

POJ Monthly–2007.10.06, SHOIT@ZSU

1.dp+二分+RMQ：dp就是处理dp[i]$dp[i]$表示i位置最远能到哪个位置，然后这一段里面没有重复，非常简单，扫两遍就行了，然后考虑到一个性质，就是dp[i]$dp[i]$是单调不减的，很明显吧，然后把idp[i]$i-dp[i]$存进RMQ里，这样就能做到O(1)$O(1)$的查询了，然后对于每次询问的一个区间[L,R]$[L,R]$,考虑这个区间里的i$i$，有些dp[i]$dp[i]$肯定是超出L$L$的，还有些i$i$dp[i]$dp[i]$是在区间里的，所以根据单调性，可以二分找到这个临界值r$r$，然后答案就是max(rL+1,RMQ(r+1,R))$max(r-L+1,RMQ(r+1,R))$

#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>

using namespace std;
#define   MAX           200005
#define   MAXN          2000005
#define   maxnode       15
#define   sigma_size    30
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   lrt           rt<<1
#define   rrt           rt<<1|1
#define   middle        int m=(r+l)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   pii           pair<int,int>
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   limit         10000

//const int    prime = 999983;
const int    INF   = 0x3f3f3f3f;
const LL     INFF  = 0x3f3f;
const double pi    = acos(-1.0);
//const double inf   = 1e18;
const double eps   = 1e-8;
const LL    mod    = 1e9+7;
const ull    mx    = 133333331;

/*****************************************************/
inline void RI(int &x){
char c;
while((c=getchar())<'0' || c>'9');
x=c-'0';
while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
/*****************************************************/

int a[MAX];
int vis[MAXN];
int dp[MAX];
int n,m;
int d[MAX][25];
void RMQ_init(){
for(int i=1;i<=n;i++) d[i][0]=i-dp[i];
for(int j=1;(1<<j)<=n;j++){
for(int i=1;i+(1<<j)-1<=n;i++){
d[i][j]=max(d[i][j-1],d[i+(1<<(j-1))][j-1]);
}
}
}

int RMQ(int L,int R){
if(L>R) return 0;
int k=0;
while((1<<(k+1))<=R-L+1) k++;
return max(d[L][k],d[R-(1<<k)+1][k]);
}

int main(){
//freopen("input.txt","r",stdin);
//freopen("out.txt","w",stdout);
cin>>n>>m;
mem(vis,0);mem(dp,0);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]+=1000000;
for(int i=1;i<=n;i++){
if(!vis[a[i]]) vis[a[i]]=i,dp[i]=0;
else{
dp[i]=vis[a[i]];
vis[a[i]]=i;
}
}
for(int i=1;i<=n;i++){
dp[i]=max(dp[i],dp[i-1]);
}
RMQ_init();
while(m--){
int aa,bb;
scanf("%d%d",&aa,&bb);
aa++,bb++;
int l=aa,r=bb;
while(l<=r){
int mid=(l+r)/2;
if(dp[mid]>=aa) r=mid-1;
else l=mid+1;
}
cout<<max(r-aa+1,RMQ(l,bb))<<endl;
}
return 0;
}

2.dp+离线线段树：dp的方法和上面一样，然后就是离线区间处理，重点在于区间怎么排序，线段树维护什么值。这方面我比较弱，参考学长的，按照区间的右端点排序，然后线段树维护什么呢，对于一个位置i$i$,把区间[dp[i]+1,i]$[dp[i]+1,i]$里都加1，这样表示区间里这些位置，被多少个（不重复出现的串）包含在里面，这里不好表述，需要自己想一下，然后查询的时候就是query(l,r)$query(l,r)$，查询这个区间里，哪一个点被最多的[dp[i]+1,i]$[dp[i]+1,i]$这样的区间覆盖，这样也是考虑到dp[i]$dp[i]$是单调不减的性质呢其实，看来我离线还是太渣了otz

#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>

using namespace std;
#define   MAX           200005
#define   MAXN          2000005
#define   maxnode       15
#define   sigma_size    30
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   lrt           rt<<1
#define   rrt           rt<<1|1
#define   middle        int m=(r+l)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   pii           pair<int,int>
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   limit         10000

//const int    prime = 999983;
const int    INF   = 0x3f3f3f3f;
const LL     INFF  = 0x3f3f;
const double pi    = acos(-1.0);
//const double inf   = 1e18;
const double eps   = 1e-8;
const LL    mod    = 1e9+7;
const ull    mx    = 133333331;

/*****************************************************/
inline void RI(int &x){
char c;
while((c=getchar())<'0' || c>'9');
x=c-'0';
while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
}
/*****************************************************/

int a[MAX];
int vis[MAXN];
int dp[MAX];
int n,m;
int maxv[MAX<<2];
struct que{
int l,r,id,ans;
}p[MAX];
bool cmp1(que a,que b){
return a.r<b.r;
}
bool cmp2(que a,que b){
return a.id<b.id;
}
void pushup(int rt){
maxv[rt]=max(maxv[lrt],maxv[rrt]);
}

void pushdown(int rt){
}
}

void build(int l,int r,int rt){
if(l==r) return ;
middle;
build(lson);
build(rson);
}

void update(int l,int r,int rt,int L,int R,int d){
if(L<=l&&r<=R){
maxv[rt]+=d;
return ;
}
pushdown(rt);
middle;
if(L<=m) update(lson,L,R,d);
if(R>m) update(rson,L,R,d);
pushup(rt);
}

int query(int l,int r,int rt,int L,int R){
if(L<=l&&r<=R) return maxv[rt];
middle;
pushdown(rt);
int ans=0;
if(L<=m) ans=max(ans,query(lson,L,R));
if(R>m) ans=max(ans,query(rson,L,R));
pushup(rt);
return ans;
}

int main(){
//freopen("input.txt","r",stdin);
//freopen("out.txt","w",stdout);
cin>>n>>m;
mem(vis,0);mem(dp,0);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]+=1000000;
for(int i=1;i<=n;i++){
if(!vis[a[i]]) vis[a[i]]=i,dp[i]=0;
else{
dp[i]=vis[a[i]];
vis[a[i]]=i;
}
}
for(int i=1;i<=n;i++){
dp[i]=max(dp[i],dp[i-1]);
}
build(1,n,1);
for(int i=0;i<m;i++){
int x,y;
scanf("%d%d",&x,&y);
x++,y++;
p[i]=(que){x,y,i};
}
sort(p,p+m,cmp1);
int tmp=1;
for(int i=0;i<m;i++){
while(tmp<=p[i].r){
update(1,n,1,dp[tmp]+1,tmp,1);
tmp++;
}
p[i].ans=query(1,n,1,p[i].l,p[i].r);
}
sort(p,p+m,cmp2);
for(int i=0;i<m;i++) printf("%d\n",p[i].ans);
return 0;
}


#### codeforces.contest/833/problem/B(DP+线段树维护最大值)

2017-08-02 17:27:49

#### test 零食店 （dp+二分）

2016-11-06 17:45:10

#### hdu3433(dp+二分)

2016-06-07 20:07:07

#### 【BZOJ】栅栏-线段树优化DP

2018-03-19 23:08:14

#### The Battle of Chibi HDU - 5542 (dp+离散化+树状数组优化)

2017-10-05 17:47:46

#### hdu 3450 离散化+dp+线段树优化

2015-08-29 16:01:46

#### [dp+树状数组优化] CF597C. Subsequences

2016-03-27 11:33:44

#### bzoj 1949 [Ceoi2006]Walk dp 线段树

2016-12-01 20:58:38

#### hdu2227 Find the nondecreasing subsequences（dp+线段树or树状数组优化）

2017-10-05 15:41:08

#### poj 3419 Difference Is Beautiful 离线线段树

2015-11-04 21:10:33

## 不良信息举报

poj 3419 Difference Is Beautiful （dp+二分+RMQ或者dp+离线线段树）