1. 程式人生 > >牛客網多校訓練 j題 (莫隊)

牛客網多校訓練 j題 (莫隊)

時間限制:C/C++ 2秒,其他語言4秒
空間限制:C/C++ 524288K,其他語言1048576K
64bit IO Format: %lld

題目描述

Given a sequence of integers a1, a2, ..., an and q pairs of integers (l1, r1), (l2, r2), ..., (lq, rq), find count(l1, r1), count(l2, r2), ..., count(lq, rq) where count(i, j) is the number of different integers among a1, a2, ..., ai, aj, aj + 1, ..., an.

輸入描述:

The input consists of several test cases and is terminated by end-of-file.
The first line of each test cases contains two integers n and q.
The second line contains n integers a1, a2, ..., an.
The i-th of the following q lines contains two integers li and ri.

輸出描述:

For each test case, print q integers which denote the result.

示例1

輸入

複製

3 2
1 2 1
1 2
1 3
4 1
1 2 3 4
1 3

輸出

複製

2
1
3

備註:

* 1 ≤ n, q ≤ 105
* 1 ≤ ai ≤ n
* 1 ≤ li, ri ≤ n
* The number of test cases does not exceed 10.

之前莫隊只做過一道題,應用到這題的時候就顯得不夠熟練,出了很多錯誤

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#define ls 2*rt
#define rs 2*rt+1
#define lson ls,L,mid
#define rson rs,mid+1,R
#define ll long long
using namespace std;
typedef pair<int,int> pii;
const ll inf = 0x3f3f3f3f;
/*void dis(int a[], int n){
    printf("總數為%d個\n",n);
    for(int i = 0; i < n; i++)   cout<<a[i]<<", ";
    cout<<endl<<"------------------"<<endl;      
}*/
  
const int mx = 1e5+10;
 
int vis[mx],a[mx];
int n,m,l,r,te;
int ans[mx],sum;
struct no{
    int l,r,id;
}q[mx];
 
bool cmp(no &a, no &b){
    if(a.l/500 != b.l/500)    //沒有除以500會超時 
        return a.l < b.l;
    else
        return a.r < b.r;
}
 
void add(int x){
    vis[a[x]]--;
    if(!vis[a[x]])
        sum--;
}
void dele(int x){
	vis[a[x]]++;
	if(vis[a[x]] == 1)    // 腦袋昏昏這句話沒有寫 
		sum++;
}
int main(){
    //int T=10;
     
    while(scanf("%d%d",&n,&m) != EOF){
     
            memset(vis,0,sizeof(vis));
            sum = 0;
        for(int i = 1; i <= n ;i++){
                scanf("%d",a+i);
                if(!vis[a[i]]){
                    sum++;
                }
                vis[a[i]]++;
            }
        int tol = sum;               
        for(int i = 1; i <= m; i++){
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].id = i;
        }
        sort(q+1,q+m+1,cmp);
        l = 0; r = 0;
        int flag = 1;
        for(int i = 1;i <= m; i++){
            if(q[i].r - q[i].l <= 1){
                ans[q[i].id] = tol;     //是tol不是sum 
                continue;
            }
            q[i].l++;
            q[i].r--;
            if(flag){
                l = r = q[i].l;
                add(l);
                flag = 0;
            }
            //printf("l =%d r =%d  L = %d\n",q[i].l,q[i].r,l);
            while(q[i].l < l)         
                add(--l);
            while(q[i].l > l)
                dele(l++);			//前增和後增得仔細 
         
            while(q[i].r < r)
                dele(r--);
                 
            while(q[i].r > r)
                add(++r);
                 
            ans[q[i].id] = sum;                
        }
         
         
        for(int i = 1; i <= m; i++)
            printf("%d\n",ans[i]);
    }
    return 0;
}

樹狀陣列的寫法思想感覺很強

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#define ls 2*rt
#define rs 2*rt+1
#define lson ls,L,mid
#define rson rs,mid+1,R
#define ll long long
#define mem(a,x) memset(a,x,sizeof(a))
using namespace std;
typedef pair<int,int> pii;
const ll inf = 0x3f3f3f3f;
/*void dis(int a[], int n){
    printf("總數為%d個\n",n);
    for(int i = 0; i < n; i++)   cout<<a[i]<<", ";
    cout<<endl<<"------------------"<<endl;      
}*/
  
const int mx = 1e5+10;
 
int node[mx],a[mx],first[mx],last[mx];
int n,m,l,r,te;
int ans[mx],sum;
struct no{
    int l,r,id;
}q[mx];
 
bool cmp(no &a, no &b){
     return a.l > b.l;
}
 
void  add(int x ,int k){
	
	while(x <= n){
		node[x] += k;
		x += x&(-x);
	}  
    
}  
 
int sea(int x){  
    int ans = 0;
   	while(x){
	 ans += node[x];
	 x -= x&(-x);    
	}
    
    return ans;  
}
  
int que(int a, int b){
	return sea(b) - sea(a-1);
}
int main(){
    //int T=10;
    //freopen("F:\\in.txt","r",stdin);
    while(scanf("%d%d",&n,&m) != EOF){
           
        sum = 0;
        mem(first,0);
        mem(last,0);
        mem(node,0);
        for(int i = 1; i <= n ;i++){
                scanf("%d",a+i);
                if(!first[a[i]]){
                    first[a[i]] = i;
                    sum++;
                }
                last[a[i]] = i;
            }
        int tol = sum;
        for(int i = 1; i <= m; i++){
            scanf("%d%d",&q[i].l,&q[i].r);
            q[i].id = i;
        }
        sort(q+1,q+m+1,cmp);
       
       	int now = n;
       	
		te = a[now];
		if(first[te] == now)
			add(last[te],1);
				
        for(int i = 1;i <= m; i++){
            if(q[i].r - q[i].l <= 1){
                ans[q[i].id] = tol;
                continue;
            }
            l = q[i].l+1;
            r = q[i].r-1;
           	while(l < now){
				now--;
				te = a[now];
			//	printf("te =%d\n",te); 
				if(first[te] == now)
					add(last[te],1);
			}
		//	printf("l =%d , r =%d\n",l,r);
			
            ans[q[i].id] = tol - que(l,r);  
			              
        }
         
        for(int i = 1; i <= m; i++)
            printf("%d\n",ans[i]);
    }
    return 0;
}