zoukankan      html  css  js  c++  java
  • CF558E A simple task 线段树

    这道题好猥琐啊啊啊啊啊啊

    写了一个上午啊啊啊啊
    没有在update里写pushup啊啊啊啊

    题目大意:

    给你一个字符串s,有q个操作
    l r 1 :把sl..rsl..r按升序排序
    l r 0 :把sl..rsl..r按降序排序

    Solution:

    我们考虑建26棵线段树,第i棵线段树的[x,y]表示在[x,y]中一共有多少个字母'a'+i-1
    至于修改时我们可以以升序为例,从a至z按顺序往前丢,记得要清空区间
    同理,降序反过来就是了

    Code:

    我们可以用sort啊啊,只不过会TLE

    #pragma GCC optimize(3)
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
     
    using namespace std;
     
    int n,q;
    char s[100001];
     
    bool cmp(char a,char b){
        return a>b;
    }
     
    int main(){
        scanf("%d%d%s",&n,&q,s);
        for(int i=1;i<=q;i++){
            int l,r,x;
            scanf("%d%d%d",&l,&r,&x);
            if(x==1)sort(s+l-1,s+r);
            else sort(s+l-1,s+r,cmp);
            printf("%s
    ",s);
        }
        printf("
    %s",s);
        return 0;
    }
    

    这里才是正解代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    char s[1000001];     
    int n,m,sum[27][400001],lazy[27][400001];
    
    inline int rd(){
    	register int x=0,y=1;
    	register char c=getchar();
    	while(c>'9' or c<'0'){
    		if(c=='-'){
    			y=-1;
    		}
    		c=getchar();
    	}
    	while(c>='0' and c<='9'){
    		x=(x<<1)+(x<<3)+(c^48);
    		c=getchar();
    	}
    	return x*y;
    }
    
    inline void pushup(int o,int rt){
    	sum[rt][o]=sum[rt][o<<1]+sum[rt][o<<1|1];
    }
    
    inline void pushdown(int o,int l,int r,int rt){
    	if(lazy[rt][o]!=-1){
    		int mid=(l+r)>>1;
    		sum[rt][o]=lazy[rt][o]*(r-l+1);
    		sum[rt][o<<1]=lazy[rt][o]*(mid-l+1);
    		sum[rt][o<<1|1]=lazy[rt][o]*(r-mid);
    		lazy[rt][o<<1]=lazy[rt][o<<1|1]=lazy[rt][o];
    		lazy[rt][o]=-1;
    	}
    }
    
    void build(int o,int l,int r){
    	if(l==r){
    		sum[s[l]-'a'+1][o]=1;
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(o<<1,l,mid);
    	build(o<<1|1,mid+1,r);
    	for(int i=1;i<=26;i++)pushup(o,i);
    }
    
    inline int query(int o,int l,int r,int x,int y,int rt){
    	if(x<=l and y>=r){
    		return sum[rt][o];
    	}
    	pushdown(o,l,r,rt);
    	int mid=(l+r)>>1,ret=0;
    	if(x<=mid)ret+=query(o<<1,l,mid,x,y,rt);
    	if(y>mid)ret+=query(o<<1|1,mid+1,r,x,y,rt);
    	return ret;
    }
    
    inline void update(int o,int l,int r,int x,int y,int rt,int v){
    	if(x<=l and y>=r){
    		lazy[rt][o]=v;
    		sum[rt][o]=v*(r-l+1);
    		return;
    	}
    	pushdown(o,l,r,rt);
    	int mid=(l+r)>>1;
    	if(x<=mid)update(o<<1,l,mid,x,y,rt,v);
    	if(y>mid)update(o<<1|1,mid+1,r,x,y,rt,v);
    	pushup(o,rt);
    }
    
    void output(int o,int l,int r){
    	if(l==r){
    		for(int i=1;i<=26;i++){
    			if(sum[i][o]){
    				s[l]='a'+i-1;
    				break;
    			}
    		}
    		return;
    	}
    	for(int i=1;i<=26;i++)pushdown(o,l,r,i);
    	int mid=(l+r)>>1;
    	output(o<<1,l,mid);
    	output(o<<1|1,mid+1,r);
    }
    
    int main(){
    	for(int i=1;i<=26;i++)memset(lazy[i],-1,sizeof(lazy[i]));
    	n=rd(),m=rd();
    	scanf("%s",s+1);
    	build(1,1,n);
    	while(m--){
    		int x=rd(),y=rd();
    		if(rd()){
    			int tmp=x-1;
    			for(int i=1;i<=26;i++){
    				int cas=query(1,1,n,x,y,i);
    				if(!cas)continue;
    				update(1,1,n,x,y,i,0);
    				update(1,1,n,tmp+1,tmp+cas,i,1);tmp=tmp+cas;
    			}
    		}else {
    			int tmp=x-1;
    			for(int i=26;i>=1;i--){
    				int cas=query(1,1,n,x,y,i);
    				if(!cas)continue;
    				update(1,1,n,x,y,i,0);
    				update(1,1,n,tmp+1,tmp+cas,i,1);tmp=tmp+cas;
    			}
    		}
    	}
    	output(1,1,n);
    	printf("%s
    ",s+1);
    	return 0;
    }
    
  • 相关阅读:
    moss jscript
    CSS两端对准
    简单的日期格式验证
    .NET中使用Exchange 2007 Webservice来读取邮件
    张二狗
    spcontext
    Infopath表单用改控件值提交或作别的更改时一定要在控件属性浏览器表单的回发设置为始终.
    使用 Web 服务
    SharePoint 2010中开发模式的改进 COM 客户端对象模型
    Retrieve data from Separate Oracle System
  • 原文地址:https://www.cnblogs.com/ezoihy/p/9313336.html
Copyright © 2011-2022 走看看