CF-558E (线段树/分块)
解题思路:
很显然突破口就是字符集比较小,分块和线段树都能A
话说线段树时间是分块5倍啊
代码(线段树):
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lll spc<<1
#define rrr spc<<1|1
struct int_26{
int has[];
void res(void)
{
memset(has,,sizeof(has));
return ;
}
int_26 friend operator + (int_26 x,int_26 y)
{
int_26 ans;
for(int i=;i<=;i++)
ans.has[i]=x.has[i]+y.has[i];
return ans;
}
}isr;
struct trnt{
int_26 val;
int lzt;
}tr[];
int n,q;
int ans[];
char cmd[];
void pushup(int spc)
{
tr[spc].val=tr[lll].val+tr[rrr].val;
return ;
}
void pushdown(int spc,int l,int r)
{
if(tr[spc].lzt)
{
int mid=(l+r)>>;
tr[lll].lzt=tr[spc].lzt;
tr[rrr].lzt=tr[spc].lzt;
tr[spc].lzt=;
tr[lll].val.res();
tr[rrr].val.res();
tr[lll].val.has[tr[lll].lzt]=mid-l+;
tr[rrr].val.has[tr[rrr].lzt]=r-mid;
}
return ;
}
void build(int spc,int l,int r)
{
if(l==r)
{
tr[spc].val.has[cmd[l]-'a'+]=;
return ;
}
int mid=(l+r)>>;
build(lll,l,mid);
build(rrr,mid+,r);
pushup(spc);
return ;
}
void update(int l,int r,int ll,int rr,int spc,int v)
{
if(l>rr||ll>r)
return ;
if(ll<=l&&r<=rr)
{
tr[spc].val.res();
tr[spc].val.has[v]=r-l+;
tr[spc].lzt=v;
return ;
}
int mid=(l+r)>>;
pushdown(spc,l,r);
update(l,mid,ll,rr,lll,v);
update(mid+,r,ll,rr,rrr,v);
pushup(spc);
return ;
}
int_26 query(int l,int r,int ll,int rr,int spc)
{
if(l>rr||ll>r)
return isr;
if(ll<=l&&r<=rr)
return tr[spc].val;
int mid=(l+r)>>;
pushdown(spc,l,r);
return query(l,mid,ll,rr,lll)+query(mid+,r,ll,rr,rrr);
}
void S_pushdown(int l,int r,int spc)
{
if(l==r)
{
for(int i=;i<=;i++)
if(tr[spc].val.has[i])
{
ans[l]=i;
break;
}
return ;
}
int mid=(l+r)>>;
pushdown(spc,l,r);
S_pushdown(l,mid,lll);
S_pushdown(mid+,r,rrr);
return ;
}
int main()
{
scanf("%d%d",&n,&q);
scanf("%s",cmd+);
build(,,n);
while(q--)
{
int l,r,op;
scanf("%d%d%d",&l,&r,&op);
if(l>r)
std::swap(l,r);
int_26 tmp=query(,n,l,r,);
if(op)
{
int sta=l;
for(int i=;i<=;i++)
{
if(!tmp.has[i])
continue;
update(,n,sta,sta+tmp.has[i]-,,i);
sta+=tmp.has[i];
}
}else{
int sta=l;
for(int i=;i;i--)
{
if(!tmp.has[i])
continue;
update(,n,sta,sta+tmp.has[i]-,,i);
sta+=tmp.has[i];
}
}
}
S_pushdown(,n,);
for(int i=;i<=n;i++)
printf("%c",ans[i]+'a'-);
return ;
}
代码(分块):
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
struct Area{
int l,r;
int lzt;//1 shenx -1 jiangx 0 wu
int has[];
}p[];
int n,q;
int a[];
int blg[];
int tmp[];
char cmd[];
bool cmp(int x,int y)
{
return x<y;
}//shenx
bool cmq(int x,int y)
{
return x>y;
}//jiangx
void P_sort(int x)
{
if(!p[x].lzt)
return ;
if(p[x].lzt==)
{
int t=;
for(int i=p[x].l;i<=p[x].r;i++)
{
while(!p[x].has[t])
t++;
a[i]=t;
p[x].has[t]--;
}
}
if(p[x].lzt==-)
{
int t=;
for(int i=p[x].l;i<=p[x].r;i++)
{
while(!p[x].has[t])
t--;
a[i]=t;
p[x].has[t]--;
}
}
p[x].lzt=;
return ;
}
void build(int x)
{
for(int i=;i<=;i++)
p[x].has[i]=;
for(int i=p[x].l;i<=p[x].r;i++)
p[x].has[a[i]]++;
return ;
}
int main()
{
scanf("%d%d",&n,&q);
if(n<=)
{
scanf("%s",cmd+);
for(int i=;i<=n;i++)
a[i]=cmd[i]-'a'+;
for(int i=;i<=q;i++)
{
int l,r,op;
scanf("%d%d%d",&l,&r,&op);
if(l>r)
std::swap(l,r);
if(op==)
std::sort(a+l,a+r+,cmq);
else
std::sort(a+l,a+r+,cmp);
}
for(int i=;i<=n;i++)
printf("%c",a[i]+'a'-);
puts("");
return ;
}
scanf("%s",cmd+);
int stan=(sqrt(n));
for(int i=;i<=n;i++)
{
a[i]=cmd[i]-'a'+;
blg[i]=i/stan+;
p[blg[i]].has[a[i]]++;
if(blg[i]!=blg[i-])
{
p[blg[i]].l=i;
p[blg[i-]].r=i-;
}
}
p[blg[n]].r=n;
while(q--)
{
int l,r,op;
scanf("%d%d%d",&l,&r,&op);
if(l>r)
std::swap(l,r);
if(blg[l]==blg[r])
{
if(op==)
std::sort(a+l,a+r+,cmq);
else
std::sort(a+l,a+r+,cmp);
continue;
}
memset(tmp,,sizeof(tmp));
P_sort(blg[l]);
build(blg[l]);
P_sort(blg[r]);
build(blg[r]);
for(int i=l;i<=p[blg[l]].r;i++)
tmp[a[i]]++;
for(int i=p[blg[r]].l;i<=r;i++)
tmp[a[i]]++;
for(int i=;i<=;i++)
for(int j=blg[l]+;j<=blg[r]-;j++)
tmp[i]+=p[j].has[i];
if(op==)
{
int t=;
for(int i=l;i<=p[blg[l]].r;i++)
{
while(!tmp[t])
t--;
tmp[t]--;
a[i]=t;
}
build(blg[l]);
for(int i=blg[l]+;i<=blg[r]-;i++)
{
int len=p[i].r-p[i].l+;
for(int j=;j<=;j++)
p[i].has[j]=;
while(tmp[t]<len)
{
p[i].has[t]+=tmp[t];
len-=tmp[t];
tmp[t]=;
t--;
}
if(len)
{
p[i].has[t]+=len;
tmp[t]-=len;
if(!tmp[t])
t--;
}
p[i].lzt=-;
}
for(int i=p[blg[r]].l;i<=r;i++)
{
while(!tmp[t])
t--;
tmp[t]--;
a[i]=t;
}
build(blg[r]);
}else{
int t=;
for(int i=l;i<=p[blg[l]].r;i++)
{
while(!tmp[t])
t++;
tmp[t]--;
a[i]=t;
}
build(blg[l]);
for(int i=blg[l]+;i<=blg[r]-;i++)
{
int len=p[i].r-p[i].l+;
for(int j=;j<=;j++)
p[i].has[j]=;
while(tmp[t]<len)
{
p[i].has[t]+=tmp[t];
len-=tmp[t];
tmp[t]=;
t++;
}
if(len)
{
p[i].has[t]+=len;
tmp[t]-=len;
if(!tmp[t])
t++;
}
p[i].lzt=;
}
for(int i=p[blg[r]].l;i<=r;i++)
{
while(!tmp[t])
t++;
tmp[t]--;
a[i]=t;
}
build(blg[r]);
}
}
for(int i=;i<=blg[n];i++)
P_sort(i);
for(int i=;i<=n;i++)
printf("%c",a[i]+'a'-);
puts("");
return ;
}
CF-558E (线段树/分块)的更多相关文章
- 洛谷 P5897 - [IOI2013]wombats(决策单调性优化 dp+线段树分块)
题面传送门 首先注意到这次行数与列数不同阶,列数只有 \(200\),而行数高达 \(5000\),因此可以考虑以行为下标建线段树,线段树上每个区间 \([l,r]\) 开一个 \(200\times ...
- BZOJ 1798 (线段树||分块)的标记合并
我原来准备做方差的.. 结果发现不会维护两个标记.. 就是操作变成一个 a*x+b ,每次维护a , b 即可 加的时候a=1 ,b=v 乘的时候a=v ,b=0 #include <cstdi ...
- [luogu1198][bzoj1012][JSOI2008]最大数【线段树+分块】
题目描述 区间查询最大值,结尾插入,强制在线. 分析 线段树可以做,但是练了一下分块,发现自己打错了两个地方,一个是分块的地方把/打成了%,还有是分块的时候标号要-1. 其他也没什么要多讲的. 代码 ...
- L3-2 森森快递 (30 分)(贪心+线段树/分块)
题目链接:https://pintia.cn/problem-sets/1108203702759940096/problems/1108204121661857798 题目大意: 森森开了一家快递公 ...
- 计蒜客16492 building(二分线段树/分块)
题解: 考虑用线段树维护楼的最大值,然后这个问题就很简单了. 每次可以向左二分出比x高的第一个楼a,同理也可以向右二分出另一个楼b,如果a,b都存在,答案就是b-a-1. 注意到二分是可以直接在线段树 ...
- IOI 2013 袋熊(线段树+分块+决策单调性)
题意 http://www.ioi2013.org/wp-content/uploads/tasks/day1/wombats/Wombats%20zh%20(CHN).pdf 思路 我们设矩形的 ...
- bzoj 3585 mex - 线段树 - 分块 - 莫队算法
Description 有一个长度为n的数组{a1,a2,...,an}.m次询问,每次询问一个区间内最小没有出现过的自然数. Input 第一行n,m. 第二行为n个数. 从第三行开始,每行一个询问 ...
- 【模拟8.05】优美序列(线段树 分块 ST算法)
如此显然的线段树,我又瞎了眼了 事实上跟以前的奇袭很像....... 只要满足公式maxn-minn(权值)==r-l即可 所以可以考虑建两颗树,一棵节点维护位置,一棵权值, 每次从一棵树树上查询信息 ...
- CF 19D 线段树+set压缩坐标轴+离散化map
题意: n个操作,在200000*200000的平面上加删点 find 严格在坐标右上角,x最小,再y最小的点 线段树做,区间为离散化后的 X轴坐标 ,维护区间点数 和 最小的 y 值 ( 维护最小y ...
随机推荐
- 同一个事务里 查询 已删除可是未提交的数据[bug记录]
前几天犯了个低级错误.在一个事务方法里老是查询不到某条记录,可是debug卡住时,用db工具查.又能查出值. 经过一番折腾,原来是我在同一个事务里 查询 了已删除可是未提交的数据.当然查询不到了! . ...
- mysql二进制日志文件出错导致mysql服务无法启动
今天打开phpmyadmin发现连不上mysql数据库,重新启动mysql启动不起来,查看日志发现例如以下错误 <span style="font-family:SimSun;font ...
- vim基础学习之EX命令
:tabnew -创建新标签 :split(sp)-垂直分割窗口 如果没有打开新的文件,那么会打开原来窗口的文件 :vsplit(vsp)-水平分割窗口 如果没有打开新的文件,那么会打开原来窗口的文件 ...
- bind DNS搭建笔记
设置默认网关 偶尔会出现问题 route add default gw 192.168.0.1 .vim /etc/sysctl.conf 这里是重点 配置路由转发,路由开启等都要用到. # Cont ...
- Firewalld 用法解析
其实还是我写的啦 https://www.jianshu.com/p/3444d9413461 1.防火墙firewall的基本概述 现在的RedHat/CentOS7版本默认都使用firewall防 ...
- Linux Cgroups
目录 Linux Cgroups Cgroups中的三个组件 三个组件的关系 Kernel接口 Docker是如何使用Cgroups的 Go语言实现Cgroups限制容器资源 Linux Cgroup ...
- caioj 1065 动态规划入门(一维一边推3:合唱队形)
就是最长上升子序列,但是要用n^2的算法. #include<cstdio> #include<algorithm> #define REP(i, a, b) for(int ...
- 关于命令行签名时.SF和.RSA文件的命名问题
准备工作: 签名文件名称为android.keystore 签名的别名为123456789.keystore 1.使用签名命令后例如以下图 发现.SF和.RSA文件自己主动命名为12345678.SF ...
- 目标决定人生——没有目标就失去一切 (没有目标的奋斗是浪费青春,比如交了钱却不去参加考试、让时间白白溜走。根据目标与定位来选择最合适的企业。人生要算总账)good
没有目标就失去一切 刚毕业那会儿,幼稚得可笑,老跟同学打电话,明面上聊聊近况,暗地里比较.你要比我工资多一百块,心里特不平衡,凭什么呀,在学校那会儿公认的我比你强.你要带个头衔,而我啥也不是,普通员工 ...
- android-从官网下拉源码(ubuntu)
今天终于成功的从谷歌官网上下载了android 源码.中间折腾了好久,最终总算有所收获 1.下载repo curl https://storage.googleapis.com/git-repo-do ...