• 【gmoj】【线段树】矮人排队


    【gmoj】【线段树】矮人排队

    题目

    P3236


    解题思路

    暴力想法就是判断编号A~B的小矮人位置最大值减最小值是否等于B-A
    但是时间复杂度达到O(NM)
    想到查询位置时可以用线段树优化一丢丢长


    代码

    暴力

    #include
    #include
    using namespace std;
    int n,m,x,l,r,a[200010],w[200010];
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		w[a[i]]=i;
    	}
    	while (m--)
    	{
    		  scanf("%d%d%d",&x,&l,&r);
    		  if (x==1)
    		  {
    		  	 swap(w[a[l]],w[a[r]]);
    		  	 swap(a[l],a[r]);
    		  } 
    		  else {
    		  	  int mi=1e9,ma=0;
    		  	  for (int i=l;i<=r;i++)
    		  	      mi=min(mi,w[i]),ma=max(ma,w[i]);
    		  	  if (ma-mi==r-l) printf("YES\n");
    				 else printf("NO\n"); 
    		  }
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    正解

    #include
    #include
    #include
    #include 
    using namespace std;
    int n,m,x,y,z,d1,d2;
    int a[200010],w[200010],ma[1000100],mi[1000010];
    void build(int l,int r,int k)
    {
    	 if (l==r)
    	 {
    	 	ma[k]=mi[k]=w[l];
    	 	return;
    	 }
    	 int mid=(l+r)/2;
    	 build(l,mid,k*2);
    	 build(mid+1,r,k*2+1);
    	 ma[k]=max(ma[k*2],ma[k*2+1]);
    	 mi[k]=min(mi[k*2],mi[k*2+1]);
    }
    void change(int l,int r,int k,int q)
    {
    	 if (l==r)
    	 {
    	 	ma[k]=mi[k]=w[l]; 
    	 	return;
    	 }
    	 int mid=(l+r)/2;
    	 if (q<=mid) change(l,mid,k*2,q);
    	    else change(mid+1,r,k*2+1,q);
    	 ma[k]=max(ma[k*2],ma[k*2+1]);
    	 mi[k]=min(mi[k*2],mi[k*2+1]);
    }
    int ask1(int x,int y,int l,int r,int k)
    { 
    	 if (x<=l&&y>=r) return ma[k];
    	 int mid=(l+r)/2,da=0;
    	 if (x<=mid) da=ask1(x,y,l,mid,k*2);
    	 if (y>mid) da=max(da,ask1(x,y,mid+1,r,k*2+1));  
    	 return da; 
    }
    int ask2(int x,int y,int l,int r,int k)
    { 
    	 if (x<=l&&y>=r) return mi[k];
    	 int mid=(l+r)/2,da=1e9;
    	 if (x<=mid) da=ask2(x,y,l,mid,k*2);
    	 if (y>mid) da=min(da,ask2(x,y,mid+1,r,k*2+1)); 
    	 return da;
    }
    int main()
    {
    	memset(mi,0x7f,sizeof(mi));
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    	{
    		scanf("%d",&a[i]);
    		w[a[i]]=i;
    	}
    	build(1,n,1);
    	for (int i=1;i<=m;i++)
    	{
    		scanf("%d%d%d",&z,&x,&y);
    		if (z==1)
    		{
    			swap(a[x],a[y]);
    			w[a[x]]=x,w[a[y]]=y;
    			change(1,n,1,a[x]);
    			change(1,n,1,a[y]);
    		}
    		else {  
    			   d1=ask1(x,y,1,n,1),d2=ask2(x,y,1,n,1);
    			   if (d1-d2==y-x)
    			      printf("YES\n");
    			      else printf("NO\n");
    		}
    	}
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
  • 相关阅读:
    Docker与Docker-Compose详解
    为什么这几个表的主键有的允许为空啊?
    flex布局
    详解Java的八种基本数据类型
    2023年第二届长沙市职业技能大赛“网络安全“项目样题任务书
    REDO strand log LGWR worker
    微服务6:通信之网关
    第4.2关 标准输入输出——大连交通大学
    raft在etcd中的实现
    返回将str1编辑成str2的最小代价
  • 原文地址:https://blog.csdn.net/qq_45621109/article/details/126165545