BZOJ 3236: [Ahoi2013]作业

题目

3236: [Ahoi2013]作业

Time Limit: 100 Sec  Memory Limit: 512 MB
Submit: 732  Solved: 271

Description

BZOJ 3236: [Ahoi2013]作业_第1张图片

 

Input

BZOJ 3236: [Ahoi2013]作业_第2张图片

Output

Sample Input

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

Sample Output

2 2
1 1
3 2
2 1

HINT

 

 


N=100000,M=1000000

 

Source

题解

一道卡测评的好题!用传说的莫队算法能水过,就是我们把每个询问x0,y0看作平面上的一个点,那么暴力转移的代价就是两个点之间的距离,我们把x轴分块,这样总的转移的代价和就是O(sqrt(n)*n)的了。由于这道题需要树状数组维护一下,所以这题的复杂度是O(nsqrt(n)logn)的。

代码

  1 /*Author:WNJXYK*/
  2 #include<cstdio>
  3 #include<algorithm>
  4 using namespace std;
  5 
  6 const int Maxm=1000000;
  7 struct QuestionNode{
  8     int l,r;
  9     int a,b;
 10     int index;
 11 }; 
 12 QuestionNode quest[Maxm+10];
 13 struct AnsNode{
 14     int Ans1,Ans2;
 15 };
 16 AnsNode ans[Maxm+10];
 17 
 18 const int Maxn=100000;
 19 int cnt[Maxn+10];
 20 
 21 int siz;
 22 int n,m;
 23 int num[Maxn+10];
 24 
 25 int sum1[Maxn+10],sum2[Maxn+10],cot[Maxn+10]; 
 26 
 27 inline int remin(int a,int b){
 28     if (a<b) return a;
 29     return b;
 30 }
 31 
 32 inline bool cmp(QuestionNode a,QuestionNode b){
 33     if (cnt[a.l]<cnt[b.l]) return true;
 34     if (cnt[a.l]==cnt[b.l] && a.r<b.r) return true;
 35     return false;
 36 }
 37 
 38 inline int lowbit(int x){
 39     return x&-x;
 40 }
 41 
 42 inline void add(int c[],int x,int num){
 43     for (int i=x;i<=Maxn;i+=lowbit(i))c[i]+=num;
 44 }
 45 
 46 inline int get(int c[],int x){
 47     int res=0;
 48     for (int i=x;i;i-=lowbit(i))res+=c[i];
 49     return res;
 50 }
 51 
 52 int main(){
 53     scanf("%d%d",&n,&m);
 54     //GetCnt
 55     while(siz*siz<n) siz++;
 56     for (int i=1;i<=siz;i++){
 57         int st=siz*(i-1)+1,ed=(remin(siz*i,n));
 58         for (int j=st;j<=ed;j++){
 59             cnt[j]=i;
 60         }
 61     }    
 62     //GetNum
 63     for (int i=1;i<=n;i++) scanf("%d",&num[i]);
 64     //GetQuest
 65     for (int i=1;i<=m;i++)scanf("%d%d%d%d",&quest[i].l,&quest[i].r,&quest[i].a,&quest[i].b);
 66     for (int i=1;i<=m;i++)quest[i].index=i;
 67     //SortQuest
 68     sort(quest+1,quest+m+1,cmp);
 69     //GetAns
 70     int left=1,right=0;
 71     for (int i=1;i<=m;i++){
 72         int l=quest[i].l,r=quest[i].r;
 73         int a=quest[i].a,b=quest[i].b;
 74         int index=quest[i].index;
 75         while (left<l){
 76             cot[num[left]]--;
 77             add(sum1,num[left],-1);
 78             if (cot[num[left]]==0) add(sum2,num[left],-1);
 79             left++;
 80         }
 81         while(l<left){
 82             left--;
 83             cot[num[left]]++;
 84             add(sum1,num[left],1);
 85             if (cot[num[left]]==1) add(sum2,num[left],1);
 86         }
 87         while(right<r){
 88             right++;
 89             cot[num[right]]++;
 90             add(sum1,num[right],1);
 91             if (cot[num[right]]==1) add(sum2,num[right],1);
 92         }
 93         while(r<right){
 94             cot[num[right]]--;
 95             add(sum1,num[right],-1);
 96             if (cot[num[right]]==0) add(sum2,num[right],-1);
 97             right--;
 98         }
 99         ans[index].Ans1=get(sum1,b)-get(sum1,a-1);
100         ans[index].Ans2=get(sum2,b)-get(sum2,a-1);
101     }
102     //Print
103     for (int i=1;i<=m;i++) printf("%d %d\n",ans[i].Ans1,ans[i].Ans2);
104     return 0;
105 }
View Code

 

你可能感兴趣的:(ZOJ)