HDU-5172-GTY's gay friends-线段树单点更新
来源:互联网 发布:gis矢量数据下载 编辑:程序博客网 时间:2024/04/24 09:16
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5172
题意:给出n个数,m个询问,问你[l,r]区间内是否为1到r-l+1的全排列。 大小很容易我们通过记录前缀和很容易求出来,但是关键是去重。 考虑线段树做法,我们记录每个点的靠左最近的相同元素的位置,然后求 整个区间的最大值(即最大的前驱)如果小于l,即满足条件,输出YES。
好吧,其实这个题目我是搜的RMQ算法出来的,因为我想练一下RMQ算法,所以我就看了一下别人的博客,自己也写了一下,结果死活MLE。。。
好吧,我仔细看了一下,1000000的数据量用RMQ开一个二维数组1000000*20,显然会超内存。。。
结果我不得不老老实实的滚回去用线段树写了。。。orz....
RMQ的MLE代码:
#include<iostream>#include<string>#include<cstdio>#include<cstring>#include<queue>#include<map>#include<cmath>#include<stack>#include<set>#include<vector>#include<algorithm>#define LL long long#define inf 1<<30#define sf(a) scanf("%d",&a);#define CLEAR(a,b) memset(a,b,sizeof(a))using namespace std;/* TLE...显然超内存;*/const int N=1000005;int n,m,a,b;int num[N],pre[N];int dp[N][21];int sum[N];void ST(int len){ for(int i=1;i<=n;i++) dp[i][0]=num[i]; for(int j=1;1<<j < n;j++){ for(int i=1;i+(1<<j)-1<n;i++){ dp[i][j]=max(dp[i][j-1],dp[i+1<<(j-1)][j-1]); } }}int rmq(int s,int v){ int k=(int)(log(v-s+1)*1.0/log(2.0)); return max(dp[s][k],dp[v-1<<k+1][k]);}int main(){ while(~scanf("%d%d",&n,&m)){ CLEAR(pre,0); CLEAR(sum,0); for(int i=1;i<=n;i++){ sf(a); sum[i]+=sum[i-1]+a; num[i]=pre[a]; pre[a]=i; } ST(n); while(m--){ sf(a);sf(b); double tmp=(b-a+2)*(b-a+1)*1.0/2.0; if(tmp!=sum[b]-sum[a-1]){ //cout<<tmp<<' '<<sum[b]-sum[a-1]<<' '; printf("NO\n"); continue; }else{ if(rmq(a,b)<a) printf("YES\n"); else printf("NO\n"); } } } return 0;}
线段树AC代码:
#include<iostream>#include<string>#include<cstdio>#include<cstring>#include<queue>#include<map>#include<cmath>#include<stack>#include<set>#include<vector>#include<algorithm>#define LL long long#define inf 1<<30#define s(a) scanf("%d",&a)#define CLEAR(a,b) memset(a,b,sizeof(a))using namespace std;const int N=1000005;int n,m,a,b;int pre[N],sum[N]; // sum存总和,pre定位该数字上一次出现的位置;struct node{ int l,r; int pre; // 用线段树维护最近一个重复的数字;}node[N<<2];void PushUp(int rt){ node[rt].pre=max(node[rt<<1].pre,node[rt<<1|1].pre);}void build(int l,int r,int rt){ node[rt].l=l; node[rt].r=r; node[rt].pre=0; if(l!=r){ int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); }}void Insert(int v,int p,int rt){ int ll=node[rt].l,rr=node[rt].r; if(ll==rr&&p==ll){ node[rt].pre=pre[v]; return; } int mid=(ll+rr)>>1; if(p<=mid) Insert(v,p,rt<<1); else Insert(v,p,rt<<1|1); PushUp(rt);}int query(int l,int r,int rt){ int ll=node[rt].l,rr=node[rt].r; if(ll==l&&rr==r){ return node[rt].pre; } int mid=(ll+rr)>>1; if(r<=mid) return query(l,r,rt<<1); else if(l>mid) return query(l,r,rt<<1|1); else return max(query(l,mid,rt<<1),query(mid+1,r,rt<<1|1));}int main(){ while(~s(n)){ s(m); CLEAR(pre,0); CLEAR(sum,0); build(1,n,1); for(int i=1;i<=n;i++){ s(a); sum[i]+=sum[i-1]+a; Insert(a,i,1); pre[a]=i; } while(m--){ s(a);s(b); int tmp=(b-a+2)*(b-a+1)*1.0/2.0; // 如果是全排列那么最后的和必然符合这个公式; if(sum[b]-sum[a-1]!=tmp){ printf("NO\n"); continue; }else{ if(query(a,b,1)<a) printf("YES\n"); // 查询该区间最近一个重复的数字出现的位置,如果比a小,那就说明这个区间没有出现过重复的数字; else printf("NO\n"); } } } return 0;}
1 0
- HDU-5172-GTY's gay friends-线段树单点更新
- hdu 5172 GTY's gay friends 线段树
- HDU 5172 GTY's gay friends(线段树)
- HDU 5172 - GTY's gay friends (线段树)
- hdu 5172 GTY's gay friends (线段树||hash)
- HDU 5172 GTY's gay friends (预处理+线段树)
- HDU 5172 GTY's gay friends (线段树)
- HDU 5172 GTY's gay friends(线段树)
- HDOJ 题目5172 GTY's gay friends(线段树)
- Hdu 5172 GTY's gay friends
- hdu 5172 GTY's gay friends
- HDU 5172 GTY's gay friends
- HDU 5172 GTY's gay friends
- hdu 5172 GTY's gay friends(线段树+前缀和)
- HDU 5172 GTY's gay friends 线段树(排列,区间不同的数)
- hdu 5172 GTY's gay friends 线段树 (未敲)
- hdu 5172 GTY's gay friends Hash随机算法
- HDU 5172 GTY's gay friends HASH随机算法
- VS 2010 winform中使用MSChart产生柱状图、折线图、饼图
- 递归 Prime Ring Problem
- 【Android多媒体】NuPlayer for HTTP Live Streaming【5】
- epoll的几个有用转载
- Word 2010插入图片出现黑线
- HDU-5172-GTY's gay friends-线段树单点更新
- 1212121212
- linux echo命令的-n、-e两个参数
- 多锐运动下载 V1.2.4 官方版
- 快读小说iPad版 V1.6 官方版
- android "receiver not registered"
- ubuntu14.04 kylin下安装android studio
- HDOJ 1050 Moving Tables(贪心)
- 第二周第二天上课