hdu 4638 Group (莫队算法 || 离线线段树)
来源:互联网 发布:linux批量管理工具 编辑:程序博客网 时间:2024/06/05 05:48
题目大意:
n个人的编号是从1 - n ,现在他们无序的站成一排。
第 id 号人和 id-1 id +1 号人是朋友,
朋友之间可以组成group。
一个group的值等于他们人数的平方。
然后有m次询问,问给出的l r 之间能构成group值的和的最大值的group数。
思路分析 (莫队算法):
首先,我们面临着假设你知道这个区间有多少个group 你能知道得到最大值的时候group是怎么分配的么。
令 x = a + b
x^2 = (a+b)^2 = a^2 + 2ab + b^2
可以得到如果得到了group 那么就不要分裂,因为group在一起的才能组成最大值。
那么现在解决询问的问题。
我们用分块莫队算法直接跑。
用ex 记录哪个id的人存在了。
加入的时候通过判断左右两人是否存在。
然后仔细推一下就知道加入与删除的关系了。
(离线线段树)
我们假设所有新加入到树中的数就是孤立的。然后我们再去判断他左边右边是否在树中,如果在树中那么就取消他们所在区间的标记。
借着
5 1
2 1 4 3 5
1 5
更好理解这份代码。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#define maxn 100005using namespace std;int bel[maxn];int block;inline void scanf_(int &num){ char in; bool neg=false; while(((in=getchar()) > '9' || in<'0') && in!='-') ; if(in=='-'){ neg=true; while((in=getchar()) >'9' || in<'0'); } num=in-'0'; while(in=getchar(),in>='0'&&in<='9') num*=10,num+=in-'0'; if(neg) num=0-num;}inline void printf_(int num){ bool flag=false; if(num<0){ putchar('-'); num=-num; } int ans[10],top=0; while(num!=0){ ans[top++]=num%10; num/=10; } if(top==0) putchar('0'); for(int i=top-1;i>=0;i--){ char ch=ans[i]+'0'; putchar(ch); }}struct node{ int st,ed,ans,id; bool operator < (const node &cmp)const { return bel[st]<bel[cmp.st] || (bel[st]==bel[cmp.st] && ed<cmp.ed); }}Q[maxn];bool cmp_id(node a,node b){ return a.id<b.id;}int a[maxn];int ex[maxn];void modify(int num,int &tans,int add){ if(add==1) { if(ex[num-1] && ex[num+1])tans--; else if(!ex[num-1] && !ex[num+1])tans++; } else { if(ex[num-1] && ex[num+1])tans++; else if(!ex[num-1] && !ex[num+1])tans--; } ex[num]+=add;}int main(){ int T; scanf_(T); while(T--) { memset(ex,0,sizeof ex); int n,m; scanf_(n),scanf_(m); block=(int)sqrt(1.0*n); for(int i=1;i<=n;i++) { scanf_(a[i]); bel[i]=(i-1)/block+1; } for(int i=1;i<=m;i++) { scanf_(Q[i].st); scanf_(Q[i].ed); Q[i].id=i; } sort(Q+1,Q+1+m); int tans=0; for(int l=1,r=0,i=1;i<=m;i++) { if(r<Q[i].ed) { for(r=r+1;r<=Q[i].ed;r++) modify(a[r],tans,1); r--; } if(r>Q[i].ed) { for(;r>Q[i].ed;r--) modify(a[r],tans,-1); } if(l<Q[i].st) { for(;l<Q[i].st;l++) modify(a[l],tans,-1); } if(l>Q[i].st) { for(l=l-1;l>=Q[i].st;l--) modify(a[l],tans,1); l++; } Q[i].ans=tans; } sort(Q+1,Q+1+m,cmp_id); for(int i=1;i<=m;i++) { printf_(Q[i].ans); puts(""); } } return 0;}
离线线段树。
#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define lson num<<1,s,mid#define rson num<<1|1,mid+1,e#define mid ((s+e)>>1)#define maxn 100005using namespace std;int cnt[maxn<<2];void update(int num,int s,int e,int pos,int val){ if(s==e){ cnt[num]+=val; return; } if(pos<=mid)update(lson,pos,val); else update(rson,pos,val); cnt[num]=cnt[num<<1]+cnt[num<<1|1];}int query(int num,int s,int e,int l,int r){ if(l<=s && r>=e)return cnt[num]; if(r<=mid)return query(lson,l,r); else if(l>mid)return query(rson,l,r); else return query(lson,l,mid)+query(rson,mid+1,r);}struct node{ int st,ed,id,ans; bool operator < (const node &cmp)const { return ed<cmp.ed; }}Q[maxn];bool cmp_id(node a,node b){ return a.id<b.id;}int pos[maxn];int a[maxn];int main(){ int T; scanf("%d",&T); while(T--) { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); pos[a[i]]=i; } for(int i=1;i<=m;i++) { scanf("%d%d",&Q[i].st,&Q[i].ed); Q[i].id=i; } sort(Q+1,Q+1+m); int index=1; memset(cnt,0,sizeof cnt); for(int i=1;i<=n;i++) { update(1,1,n,pos[a[i]],1); if(pos[a[i]+1]<=i && a[i]<n)update(1,1,n,pos[a[i]+1],-1); if(pos[a[i]-1]<=i && a[i]>1)update(1,1,n,pos[a[i]-1],-1); while(index<=m && Q[index].ed==i) { Q[index].ans=query(1,1,n,Q[index].st,Q[index].ed); index++; } } sort(Q+1,Q+1+m,cmp_id); for(int i=1;i<=m;i++) printf("%d\n",Q[i].ans); } return 0;}
1 0
- hdu 4638 Group (莫队算法 || 离线线段树)
- hdu 4638 Group(莫队算法|离线线段树)
- hdu 4638 Group(离线线段树)
- hdu 4638 Group (线段树+离线处理)
- 离线处理(线段树|树状数组)| 莫对算法 —— HDU 4638 Group
- HDU 4638 Group (莫队算法||线段树离散查询)
- hdu 4638 Group 线段树/数状数组+离线
- HDU 4638 Group 多校第四场(线段树+离线询问)
- hdu 4638 Group(线段树,离线维护左边界,4级)
- HDU 4638 Group(莫队算法)
- hdu 4638 Group(莫队算法)
- HDU 4638 Group 莫队算法
- HDU 4638 Group(莫队算法)
- HDU4638:Group(线段树离线处理)
- hdu4638 Group(离线线段树)
- HDU 4638 - Group(树状数组 / 线段树)
- HDU4638 Group (线段树,莫队算法)
- [HDU 3333] Turing Tree (线段树+离线算法)
- Python 字符串操作
- 发的发生地方的实打实
- 用CSS border相关属性画三角形
- 计算机网络知识(路由器交换机的配置)
- Hadoop工作流引擎之Oozie3.3.2
- hdu 4638 Group (莫队算法 || 离线线段树)
- OC基础知识汇总
- 【C++】两个关于vector和iterator的练习
- LeetCode | Climbing Stairs(爬楼梯)
- linux系统学习之awk命令
- poj1019 Number Sequence
- Oozie配置说明
- 使用 JavaScript 拦截和跟踪浏览器中的 HTTP 请求
- XMPP协议的优点和缺点?