zoukankan      html  css  js  c++  java
  • 【做题记录】区间排序—线段树

    1. CF558E A Simple Task

    题意:

    给定由小写字母组成的字符串 (s) 每一次操作如下:

    • (opt=0) :将 ([l,r]) 降序排序

    • (opt=1) :将 ([l,r]) 升序排序

    输出最终字符串

    题解:

    大致思想为,建 (26) 棵线段树,代表每一种字母。

    操作:区间查询出每一种字母的个数,记为 (cnt[c])

    排序:按照 (a)(z)(z)(a) 依次向后覆盖 (cnt[i]) 个位置 。

    输出答案:对于每一位,枚举 ([a,z]) ,找出覆盖这一位的字母 。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Maxn 100005
    #define Maxc 27
    int n,m;
    struct Tree
    {
    	 int sum,ch_laz;
    }tree[Maxc][Maxn<<2];
    int cnt[Maxc];
    void build(int opt,int p,int nl,int nr)
    {
    	 tree[opt][p].ch_laz=-1;
    	 if(nl==nr) return;
    	 int mid=(nl+nr)>>1;
    	 if(mid>=nl) build(opt,p<<1,nl,mid);
    	 if(mid<nr) build(opt,p<<1|1,mid+1,nr);
    }
    void pushdown(int opt,int p,int nl,int nr)
    {
    	 if(tree[opt][p].ch_laz==-1) return;
    	 int mid=(nl+nr)>>1;
    	 tree[opt][p<<1].sum=(mid-nl+1)*tree[opt][p].ch_laz;
    	 tree[opt][p<<1|1].sum=(nr-mid)*tree[opt][p].ch_laz;
    	 tree[opt][p<<1].ch_laz=tree[opt][p<<1|1].ch_laz=tree[opt][p].ch_laz;
    	 tree[opt][p].ch_laz=-1;
    }
    void pushup(int opt,int p)
    {
    	 tree[opt][p].sum=tree[opt][p<<1].sum+tree[opt][p<<1|1].sum;
    }
    void change(int opt,int p,int nl,int nr,int l,int r,int x)
    {
    	 if(nl>=l && nr<=r)
    	 {
    	 	 tree[opt][p].sum=(nr-nl+1)*x;
    	 	 tree[opt][p].ch_laz=x;
    	 	 return;
    	 }
    	 pushdown(opt,p,nl,nr);
    	 int mid=(nl+nr)>>1;
    	 if(mid>=l) change(opt,p<<1,nl,mid,l,r,x);
    	 if(mid<r) change(opt,p<<1|1,mid+1,nr,l,r,x);
    	 pushup(opt,p);
    }
    int query(int opt,int p,int nl,int nr,int l,int r)
    {
    	 if(nl>=l && nr<=r) return tree[opt][p].sum;
    	 pushdown(opt,p,nl,nr);
    	 int mid=(nl+nr)>>1,ret=0;
    	 if(mid>=l) ret+=query(opt,p<<1,nl,mid,l,r);
    	 if(mid<r) ret+=query(opt,p<<1|1,mid+1,nr,l,r);
    	 pushup(opt,p);
    	 return ret;
    }
    int main()
    {
         //freopen(".in","r",stdin);
         //freopen(".out","w",stdout);
    	 cin>>n>>m;
    	 for(int i=0;i<26;i++) build(i,1,1,n);
    	 char x;
    	 for(int i=1;i<=n;i++) cin>>x,change(x-'a',1,1,n,i,i,1);
    	 for(int i=1,l,r,k;i<=m;i++)
    	 {
    	 	 cin>>l>>r>>k;
    	 	 memset(cnt,0,sizeof(cnt));
    	 	 if(k)
    	 	 {
    		 	 for(int i=0;i<26;i++) cnt[i]=query(i,1,1,n,l,r),change(i,1,1,n,l,r,0);
    		 	 for(int i=0,pos=l;i<26;i++) if(cnt[i]) change(i,1,1,n,pos,pos+cnt[i]-1,1),pos+=cnt[i];
    		 }
    	 	 else
    	 	 {
    		 	 for(int i=25;i>=0;i--) cnt[i]=query(i,1,1,n,l,r),change(i,1,1,n,l,r,0);
    		 	 for(int i=25,pos=l;i>=0;i--) if(cnt[i]) change(i,1,1,n,pos,pos+cnt[i]-1,1),pos+=cnt[i];
    		 }
    	 }
    	 for(int i=1;i<=n;i++) for(int j=0;j<26;j++)
    		 if(query(j,1,1,n,i,i)) { printf("%c",j+'a'); break; }
    	 printf("
    ");
         //fclose(stdin);
         //fclose(stdout);
         return 0;
    }
    

    2. P2824 [HEOI2016/TJOI2016]排序

    题意:

    给定由 ([1,n]) 组成的排列,每一次操作如下:

    • (opt=0) :将 ([l,r]) 升序排序

    • (opt=1) :将 ([l,r]) 降序排序

    最后输出第 (Pos) 位的值。

    题解:

    与上一题不同的是:这里有 (n) 种元素,但是只用查询一位的值 。

    考虑二分答案!!

    二分第 (Pos) 位的取值,将大于等于 (mid) 的值都改为 (1) ,将小于 (mid) 的值都改为 (0) ,离线进行一遍所有操作。

    若操作完后第 (Pos) 位为 (1) ,则 (ansge mid) ,否则 (ans<mid)

    注意:(代码第 (72) 行)

    cnt=query(1,1,n,l[i],r[i]); 中, (cnt) 的可能为 (0) ,在接下来的覆盖中可能会出现 (l>r) ,应该及时判断 。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    #define Maxn 100005
    typedef long long ll;
    inline int rd()
    {
    	 int x=0;
         char ch,t=0;
         while(!isdigit(ch = getchar())) t|=ch=='-';
         while(isdigit(ch)) x=x*10+(ch^48),ch=getchar();
         return x=t?-x:x;
    }
    int n,m,Pos,L,R,ans;
    int a[Maxn],tmp[Maxn],opt[Maxn],l[Maxn],r[Maxn];
    struct Data
    {
    	 int sum,laz;
    }tree[Maxn<<2];
    void pushup(int p)
    {
    	 tree[p].sum=tree[p<<1].sum+tree[p<<1|1].sum;
    }
    void pushdown(int p,int nl,int nr)
    {
    	 if(tree[p].laz!=-1)
    	 {
    	 	 int mid=(nl+nr)>>1;
    	 	 tree[p<<1].sum=(mid-nl+1)*tree[p].laz;
    	 	 tree[p<<1|1].sum=(nr-mid)*tree[p].laz;
    	 	 tree[p<<1].laz=tree[p<<1|1].laz=tree[p].laz;
    	 	 tree[p].laz=-1;
    	 }
    }
    void build(int p,int nl,int nr)
    {
    	 tree[p].sum=0,tree[p].laz=-1;
    	 if(nl==nr) { tree[p].sum=tmp[nl]; return; }
    	 int mid=(nl+nr)>>1;
    	 build(p<<1,nl,mid),build(p<<1|1,mid+1,nr);
    	 pushup(p);
    }
    void change(int p,int nl,int nr,int l,int r,int k)
    {
    	 if(nl>=l && nr<=r)
    	 {
    	 	 tree[p].sum=(nr-nl+1)*k;
    		 tree[p].laz=k;
    	 	 return;
    	 }
    	 pushdown(p,nl,nr);
    	 int mid=(nl+nr)>>1;
    	 if(mid>=l) change(p<<1,nl,mid,l,r,k);
    	 if(mid<r) change(p<<1|1,mid+1,nr,l,r,k);
    	 pushup(p);
    }
    int query(int p,int nl,int nr,int l,int r)
    {
    	 if(nl>=l && nr<=r) return tree[p].sum;
    	 pushdown(p,nl,nr);
    	 int mid=(nl+nr)>>1,ret=0;
    	 if(mid>=l) ret+=query(p<<1,nl,mid,l,r);
    	 if(mid<r) ret+=query(p<<1|1,mid+1,nr,l,r);
    	 pushup(p);
    	 return ret;
    }
    bool check(int val)
    {
    	 for(int i=1;i<=n;i++) tmp[i]=(a[i]>=val)?1:0;
    	 build(1,1,n);
    	 for(int i=1,cnt;i<=m;i++)
    	 {
    	 	 cnt=query(1,1,n,l[i],r[i]);
    	 	 change(1,1,n,l[i],r[i],0);
    	 	 if(!cnt) continue;
    	 	 if(opt[i]==0) change(1,1,n,r[i]-cnt+1,r[i],1);
    	 	 else change(1,1,n,l[i],l[i]+cnt-1,1);
    	 }
    	 return query(1,1,n,Pos,Pos);
    }
    int main()
    {
         //freopen(".in","r",stdin);
         //freopen(".out","w",stdout);
    	 n=rd(),m=rd();
    	 for(int i=1;i<=n;i++) a[i]=rd();
    	 for(int i=1;i<=m;i++) opt[i]=rd(),l[i]=rd(),r[i]=rd();
    	 Pos=rd();
    	 L=1,R=n,ans=1;
    	 while(L<=R)
    	 {
    	 	 int mid=(L+R)>>1;
    	 	 if(check(mid)) ans=mid,L=mid+1;
    	 	 else R=mid-1;
    	 }
    	 printf("%d
    ",ans);
         //fclose(stdin);
         //fclose(stdout);
         return 0;
    }
    
  • 相关阅读:
    Swing 添加Esc快捷键退出程序
    DefaultTableCellRenderer 自定义
    项目清理和删除svn信息(转)
    时间转换工具类
    Java Swing 日期控件(转载)
    Eureka原理
    SpringCloud之Eureka注册中心集群篇
    spring boot及spring cloud介绍
    spring cloud 服务注册/发现/提供/调用 demo
    eclipse构建maven+scala+spark工程
  • 原文地址:https://www.cnblogs.com/EricQian/p/14397249.html
Copyright © 2011-2022 走看看