[2009国家集训队]小Z的袜子(hose)
来源:互联网 发布:java应用服务器开发 编辑:程序博客网 时间:2024/04/29 11:05
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
可怕的莫队算法。。。感觉有了这个,是不是可以解决所有的区间查询但是无修改的题目
也许不是最优的,但是O(n*sqrt(n))完全也是可以尝试的。
莫队算法:对于两个区间的查询[l1,r1] ,[l2,r2]如果每增加一个区间元素或者删除,都能做到O(1)的话
那么从[l1,r1]转移到[l2,r2],暴力可以做到|l1-l2|+|r1-r2|,就是manhattan距离
莫队的论文一直没有找到,所以只是大致的了解下,应该是证明出构造出哈密尔顿路径是最优的。
但是可以用manhattan mst来构造,大约会是两倍,然后莫队证明出这样转移的上限是O(n*sqrt(n))。
所以对于这种无修改的区间查询来说
可以先将所有的区间,看成二维平面上的点,求一次manhattan mst,然后根据mst来进行转移
相邻的两个区间的查询转移,暴力解决。
Manhattan MST 这里有
#include <iostream> #include <cstdio> #include <algorithm> #include <vector>#include <cstring>#define lowbit(x) (x&(-x)) #define LL long long using namespace std; const int N = 50005; struct Point{ int x,y,id; bool operator<(const Point p)const{ return x!=p.x?x<p.x:y<p.y; } }p[N],pp[N]; //数状数组,找(y-x)大于当前的,但是y+x最小的struct BIT{ int min_val,pos; void init(){ min_val=(1<<30); pos=-1; } }bit[N]; //所有有效边,Kruskalstruct Edge{ int u,v,d; bool operator<(const Edge e)const{ return d<e.d; } }e[N<<2]; //前向星struct Graph{ int v,next;}edge[N<<1];int n,m,tot,pre[N]; int total,start[N];int find(int x){ return pre[x]=(x==pre[x]?x:find(pre[x])); } inline int dist(int i,int j){ return abs(p[i].x-p[j].x)+abs(p[i].y-p[j].y); } inline void addedge(int u,int v,int d){ e[tot].u=u; e[tot].v=v; e[tot++].d=d; } inline void _add(int u,int v){ edge[total].v=v; edge[total].next=start[u]; start[u]=total++;}inline void update(int x,int val,int pos){ for(int i=x;i>=1;i-=lowbit(i)) if(val<bit[i].min_val) bit[i].min_val=val,bit[i].pos=pos; } inline int ask(int x,int m){ int min_val=(1<<30),pos=-1; for(int i=x;i<=m;i+=lowbit(i)) if(bit[i].min_val<min_val) min_val=bit[i].min_val,pos=bit[i].pos; return pos; } inline void Manhattan_minimum_spanning_tree(int n,Point *p){ int a[N],b[N]; for(int dir=0;dir<4;dir++){ //4种坐标变换 if(dir==1||dir==3){ for(int i=0;i<n;i++) swap(p[i].x,p[i].y); } else if(dir==2){ for(int i=0;i<n;i++){ p[i].x=-p[i].x; } } sort(p,p+n); for(int i=0;i<n;i++){ a[i]=b[i]=p[i].y-p[i].x; } sort(b,b+n); int m=unique(b,b+n)-b; for(int i=1;i<=m;i++) bit[i].init(); for(int i=n-1;i>=0;i--){ int pos=lower_bound(b,b+m,a[i])-b+1; //BIT中从1开始 int ans=ask(pos,m); if(ans!=-1) addedge(p[i].id,p[ans].id,dist(i,ans)); update(pos,p[i].x+p[i].y,i); } } sort(e,e+tot); for(int i=0;i<n;i++) pre[i]=i; for(int i=0;i<tot;i++){ int u=e[i].u,v=e[i].v; int fa=find(u),fb=find(v); if(fa!=fb){ pre[fa]=fb; _add(u,v); _add(v,u); } } } LL gcd(LL a,LL b){ return b==0?a:gcd(b,a%b);}LL up[N],down[N];LL ans;int col[N],vis[N]={0};int cnt[N]={0}; //记录每种颜色出现的次数inline void add(int l,int r){ for(int i=l;i<=r;i++){ int c=col[i]; ans-=(LL)cnt[c]*(cnt[c]-1)/2; cnt[c]++; ans+=(LL)cnt[c]*(cnt[c]-1)/2; }}inline void del(int l,int r){ for(int i=l;i<=r;i++){ int c=col[i]; ans-=(LL)cnt[c]*(cnt[c]-1)/2; cnt[c]--; ans+=(LL)cnt[c]*(cnt[c]-1)/2; }}//[l1,r1]前一个区间 [l2,r2]当前区间void dfs(int l1,int r1,int l2,int r2,int idx,int pre){ if(l2<l1) add(l2,l1-1); if(r2>r1) add(r1+1,r2); if(l2>l1) del(l1,l2-1); if(r2<r1) del(r2+1,r1); up[pp[idx].id]=ans; vis[idx]=1; for(int i=start[idx];i!=-1;i=edge[i].next){ int v=edge[i].v; if(vis[v]) continue; dfs(l2,r2,pp[v].x,pp[v].y,v,idx); } if(l2<l1) del(l2,l1-1); if(r2>r1) del(r1+1,r2); if(l2>l1) add(l1,l2-1); if(r2<r1) add(r2+1,r1);}int main(){ //freopen("input.txt","r",stdin); scanf("%d%d",&n,&m); tot=total=0; memset(start,-1,sizeof(start)); for(int i=1;i<=n;i++) scanf("%d",&col[i]); for(int i=0;i<m;i++){ scanf("%d%d",&p[i].x,&p[i].y); down[i]=(LL)(p[i].y-p[i].x+1)*(p[i].y-p[i].x)/2; p[i].id=i; pp[i]=p[i]; //副本一份,便于后面DFS,或者之后按id排序 } Manhattan_minimum_spanning_tree(m,p); for(int i=0;i<m;i++){ p[i].y=-p[i].y; } dfs(2,1,pp[0].x,pp[0].y,0,-1); for(int i=0;i<m;i++){ LL g=gcd(up[i],down[i]); printf("%lld/%lld\n",up[i]/g,down[i]/g); } return 0; }
- [2009国家集训队]小Z的袜子(hose)
- [2009国家集训队]小Z的袜子(hose) 分块做法
- bzoj2038: [2009国家集训队]小Z的袜子(hose)
- bzoj 2038: [2009国家集训队]小Z的袜子(hose)
- 【BZOJ 2038】 [2009国家集训队]小Z的袜子(hose)
- bzoj2038 [2009国家集训队]小Z的袜子(hose) (分块)
- 【转】[2009国家集训队]小Z的袜子(hose)
- bzoj2038: [2009国家集训队]小Z的袜子(hose)
- bzoj 2038: [2009国家集训队]小Z的袜子(hose)
- bzoj 2038: [2009国家集训队]小Z的袜子(hose)
- bzoj2038【2009国家集训队】小Z的袜子(hose)
- 【BZOJ2038】[2009国家集训队]小Z的袜子(hose)【莫队】
- 【BZOJ 2038】 [2009国家集训队]小Z的袜子(hose)
- 【bzoj2038】[2009国家集训队]小Z的袜子(hose) 莫队
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose)
- BZOJ 2038: [2009国家集训队]小Z的袜子(hose)
- bzoj 2038 [2009国家集训队]小Z的袜子(hose)
- 2038: [2009国家集训队]小Z的袜子(hose)
- uva 10130 - SuperSale
- Shared Pool 原理
- 机器学习中的相似性度量
- IPC
- OpenCV学习笔记(六)—序列
- [2009国家集训队]小Z的袜子(hose)
- js字符串转日期格式
- linux防火墙禁IP命令
- 网站商务通使用总结:
- 由push_back引起的复制构造函数
- Linux双网卡绑定(Redhat)
- 火狐浏览器所有的快捷键
- flex image加载图片
- 什么是WINSXS文件夹 关于VS2005程序发布的问题