[BZOJ2724][Violet 6]蒲公英(分块)
2016-03-31 23:57
435 查看
题目描述
传送门题解
预处理一坨。块外暴力。
块内sort(关键字先权值再位置),然后二分找。
代码
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<vector> #include<cmath> using namespace std; const int max_n=4e4+5; const int max_t=2e2+5; int n,m,cnt,t1,t2,l,r; int a[max_n],b[max_n],c[max_n],mp[max_n],num[max_n]; int last[max_t]; struct hp{ int val,num; }aa[max_n]; struct hq{ int l,r; }k[max_n]; int val[max_n],number[max_n]; int ans,ansk; int key[max_t][max_t],sum[max_t][max_t],s[max_n]; inline int cmp1(int x,int y){ return b[x]<b[y]; } inline int cmp(hp a,hp b){ return a.val<b.val||(a.val==b.val&&a.num<b.num); } inline void add(int i,int tot){ s[a[i]]+=tot; if (s[a[i]]>ans){ ans=s[a[i]]; ansk=mp[a[i]]; } else if (s[a[i]]==ans&&ansk>mp[a[i]]) ansk=mp[a[i]]; } inline void Query(int l,int r){ int lrange,rrange; memset(s,0,sizeof(s)); ans=ansk=0; if (num[l]==num[r]){ for (int i=l;i<=r;++i) add(i,1); printf("%d\n",ansk); return; } if (l!=last[num[l]-1]+1) lrange=num[l]+1; else lrange=num[l]; if (r!=last[num[r]]) rrange=num[r]-1; else rrange=num[r]; ans=sum[lrange][rrange]; ansk=mp[key[lrange][rrange]]; if (l!=last[num[l]-1]+1) for (int i=l;i<=last[num[l]];++i) if (!s[a[i]]){ add(i,1); int loc1=k[a[i]].l; int loc2=k[a[i]].r; int loc3=lower_bound(number+loc1,number+loc2+1,lrange)-number; if (loc3>loc2) continue; int loc4=upper_bound(number+loc1,number+loc2+1,rrange)-number-1; if (loc3>loc4) continue; int tot=loc4-loc3+1; add(i,tot); } else add(i,1); if (r!=last[num[r]]) for (int i=last[num[r]-1]+1;i<=r;++i) if (!s[a[i]]){ add(i,1); int loc1=k[a[i]].l; int loc2=k[a[i]].r; int loc3=lower_bound(number+loc1,number+loc2+1,lrange)-number; if (loc3>loc2) continue; int loc4=upper_bound(number+loc1,number+loc2+1,rrange)-number-1; if (loc3>loc4) continue; int tot=loc4-loc3+1; add(i,tot); } else add(i,1); printf("%d\n",ansk); } int main(){ scanf("%d%d",&n,&m); for (int i=1;i<=n;++i){ scanf("%d",&b[i]); c[i]=i; } sort(c+1,c+n+1,cmp1); for (int i=1;i<=n;++i) if (b[c[i]]!=b[c[i-1]]) a[c[i]]=++cnt; else a[c[i]]=cnt; for (int i=1;i<=n;++i) mp[a[i]]=b[i]; int t1=(int)sqrt(n); if (n%t1==0) t2=n/t1; else t2=n/t1+1; for (int i=1;i<=n;++i) if (i%t1==0) num[i]=i/t1; else num[i]=i/t1+1; for (int i=1;i<=t2;++i) last[i]=min(i*t1,n); for (int i=1;i<=n;++i){ aa[i].val=a[i]; aa[i].num=num[i]; } sort(aa+1,aa+n+1,cmp); for (int i=1;i<=n;++i){ val[i]=aa[i].val; number[i]=aa[i].num; } k[1].l=1; for (int i=2;i<=n;++i) if (val[i]!=val[i-1]){ k[val[i]].l=i; k[val[i-1]].r=i-1; } k[cnt].r=n; int head=0,tail=0; ans=ansk=0; while (head<=t2){ head++; tail=head; memset(s,0,sizeof(s)); ans=ansk=0; for (int i=last[head-1]+1;i<=last[head];++i){ ++s[a[i]]; if (s[a[i]]>ans){ ans=s[a[i]]; ansk=a[i]; } else if (s[a[i]]==ans&&ansk>a[i]) ansk=a[i]; } key[head][tail]=ansk; sum[head][tail]=ans; while (tail<=t2){ tail++; for (int i=last[tail-1]+1;i<=last[tail];++i){ ++s[a[i]]; if (s[a[i]]>ans){ ans=s[a[i]]; ansk=a[i]; } else if (s[a[i]]==ans&&ansk>a[i]) ansk=a[i]; } key[head][tail]=ansk; sum[head][tail]=ans; } } ans=ansk=0; for (int i=1;i<=m;++i){ scanf("%d%d",&l,&r); l=(l+ansk-1)%n+1; r=(r+ansk-1)%n+1; if (l>r) swap(l,r); Query(l,r); } }
总结
代码跑的慢。姿势太蠢?相关文章推荐
- leetcode Javascript HappyNumber
- spring事务详解
- C++实验2-3-两点距离
- Cannot create __weak reference in file using manual refrence counting.
- 计数问题
- 树莓派安装samba时出错
- 哲学初步认识5
- Java之输入
- sqlserver还原数据库的时候出现提示无法打开备份设备的解决方法(设备出现错误或设备脱)
- 编程珠玑学习笔记(第一章)
- iOS的JS和OC代码互相调用
- javaEE 分页功能最终代码优化(二)
- 线程的共享互斥
- 冒泡排序
- centos7如何调节屏幕分辨率
- 2016自考总结
- mysql DELIMITER $$
- [BZOJ3343]教主的魔法(分块)
- LeetCode之4---Median of Two Sorted Arrays
- 简单密码破解