BZOJ 3236: [Ahoi2013]作业
题目
3236: [Ahoi2013]作业
Time Limit: 100 Sec Memory Limit: 512 MBSubmit: 732 Solved: 271
Description
Input
Output
Sample Input
3 4
1 2 2
1 2 1 3
1 2 1 1
1 3 1 3
2 3 2 3
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
1 1
3 2
2 1
HINT
N=100000,M=1000000
Source
题解
一道卡测评的好题!用传说的莫队算法能水过,就是我们把每个询问x0,y0看作平面上的一个点,那么暴力转移的代价就是两个点之间的距离,我们把x轴分块,这样总的转移的代价和就是O(sqrt(n)*n)的了。由于这道题需要树状数组维护一下,所以这题的复杂度是O(nsqrt(n)logn)的。
代码
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }