博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【BZOJ】3038: 上帝造题的七分钟2 && 3211: 花神游历各国
阅读量:7011 次
发布时间:2019-06-28

本文共 2821 字,大约阅读时间需要 9 分钟。

【算法】线段树||树状数组&&并查集

【题解】修改必须暴力单点修改,然后利用标记区间查询。

优化:一个数经过不断开方很快就会变成1,所以维护区间最大值。

修改时访问到的子树最大值<=1时,该区间就不必修改。

#include
#include
#include
using namespace std;const int maxn=100010;struct treess{
int k,l,r;long long maxs,sum;}t[maxn*3];int n,m;long long a[maxn];void build(int k,int l,int r){ t[k].l=l;t[k].r=r; if(l==r)t[k].maxs=t[k].sum=a[l]; else { int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); t[k].maxs=max(t[k<<1].maxs,t[k<<1|1].maxs);//printf("k=%d maxs=%d",k,t[k].maxs); t[k].sum=t[k<<1].sum+t[k<<1|1].sum; }}void update(int k,int l,int r){ int left=t[k].l,right=t[k].r; if(t[k].maxs<=1)return; if(left==right)a[left]=floor(sqrt(a[left])),t[k].maxs=t[k].sum=a[left]; else { int mid=(left+right)>>1; if(l<=mid)update(k<<1,l,r); if(r>mid)update(k<<1|1,l,r); t[k].maxs=max(t[k<<1].maxs,t[k<<1|1].maxs); t[k].sum=t[k<<1].sum+t[k<<1|1].sum; }}long long ask(int k,int l,int r){ int left=t[k].l,right=t[k].r; if(l<=left&&right<=r)return t[k].sum; int mid=(left+right)>>1;long long ans=0; if(l<=mid)ans=ask(k<<1,l,r); if(r>mid)ans+=ask(k<<1|1,l,r); return ans;}int main(){ scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%lld",&a[i]); scanf("%d",&m); build(1,1,n); for(int i=1;i<=m;i++) { int k,l,r; scanf("%d%d%d",&k,&l,&r); if(l>r)swap(l,r); if(k==0)update(1,l,r); else printf("%lld\n",ask(1,l,r)); } return 0;}
View Code

 

并查集将ai=1的节点并起来,也就是fa[i]表示i后第一个ai≠1的节点,然后用树状数组单点修改区间维护前缀和。

带删除的寻数问题,都可以用类似的并查集套路解决。

#include
#include
#include
#include
#define lowbit(x) x&(-x)#define ll long longusing namespace std;const ll maxn=100010;ll n,m,fa[maxn],a[maxn];long long c[maxn];void modify(ll x,ll k){
for(ll i=x;i<=n;i+=lowbit(i))c[i]+=k;}long long ask(ll x){
long long as=0;for(ll i=x;i>=1;i-=lowbit(i))as+=c[i];return as;}ll find(ll x){
return fa[x]==x?x:fa[x]=find(fa[x]);}int main(){ scanf("%lld",&n); for(ll i=1;i<=n;i++)scanf("%lld",&a[i]),modify(i,a[i]); for(ll i=1;i<=n+1;i++)fa[i]=i; scanf("%lld",&m); for(ll i=1;i<=m;i++){ ll k,l,r; scanf("%lld%lld%lld",&k,&l,&r); if(l>r)swap(l,r); if(k==1)printf("%lld\n",ask(r)-ask(l-1)); else{ for(ll j=l;j<=r;j++){ j=find(j); if(j<=r){ modify(j,(ll)sqrt(a[j])-a[j]); a[j]=(ll)sqrt(a[j]); if(a[j]<=1)fa[j]=find(j+1); } } } } return 0;}
View Code

 

转载于:https://www.cnblogs.com/onioncyc/p/5845470.html

你可能感兴趣的文章
安装包大全
查看>>
Mysql 通过全量备份和binlog恢复整体数据
查看>>
使用paramiko模块在远程服务器执行命令
查看>>
Cannot change version of project facet Dynamic web
查看>>
Nginx中文手册
查看>>
jqgrid saveRow 保存行 编辑数据向后台保存的使用
查看>>
离职后的选择
查看>>
Java编写QQ邮件发送程序
查看>>
JavaWeb
查看>>
我的友情链接
查看>>
Struts2输入<无提示解决方法
查看>>
字符串资源多语言的出错问题
查看>>
集合框架
查看>>
Git 大杂烩(初学git 常用的命令)
查看>>
清除默认样式
查看>>
padding-left: 20%;position: relative; left: 50%;
查看>>
zabbix专题:第七章 添加图像Graphs,添加聚合图形Screens
查看>>
移动端随记:flexbox兼容处理
查看>>
CCIE集训营培训路由与交换的全套视频
查看>>
IOS,图片切换动画
查看>>