HDU 4893 Wow! Such Sequence 线段树暴力
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 4893 Wow! Such Sequence 线段树暴力相关的知识,希望对你有一定的参考价值。
题意:n个数 初始为0,三个操作:给某个数加上d,查询区间和,把区间[l,r]中每个a[i]变为离a[i]最近的斐波那契数,n,m<=1e5.
无操作1情况下,每个点最多变化一次,每次修改logn,算上操作1 最坏情况下修改n+m次 O((n+m)logn).
对区间设个标记 线段树暴力即可.
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; const int N=2e6+5; struct node{ int l,r; int mid(){return l+r>>1;} ll flag,sum; }t[N>>2]; int n,m; ll f[200]; ll calc(ll x) { ll mn=1e18,res; for(int i=1;i<=90;i++) { if(mn>abs(f[i]-x)) mn=abs(f[i]-x),res=f[i]; } return res; } void push_up(int rt) { t[rt].sum=t[rt<<1].sum+t[rt<<1|1].sum; t[rt].flag=t[rt<<1].flag & t[rt<<1|1].flag; } void build(int rt,int l,int r) { t[rt].l=l,t[rt].r=r; if(l==r) { t[rt].sum=0; t[rt].flag=0; return; } int m=t[rt].mid(); build(rt<<1,l,m); build(rt<<1|1,m+1,r); push_up(rt); } void setval(int rt,int pos,int d) { int l=t[rt].l,r=t[rt].r; if(l==r) { t[rt].sum+=d; t[rt].flag=0; return; } int m=t[rt].mid(); if(pos<=m) setval(rt<<1,pos,d); else setval(rt<<1|1,pos,d); push_up(rt); } ll query(int rt,int ql,int qr) { int l=t[rt].l,r=t[rt].r; if(ql<=l&&qr>=r) return t[rt].sum; ll m=t[rt].mid(),res=0; if(ql<=m) res+=query(rt<<1,ql,qr); if(qr>m) res+=query(rt<<1|1,ql,qr); return res; } void update(int rt,int ql,int qr) { int l=t[rt].l,r=t[rt].r; if(ql<=l&&qr>=r && (t[rt].flag)) return; if(l==r) { t[rt].sum=calc(t[rt].sum); t[rt].flag=1; return; } int m=t[rt].mid(); if(ql<=m) update(rt<<1,ql,qr); if(qr>m) update(rt<<1|1,ql,qr); push_up(rt); } int main() { f[0]=f[1]=1; for(int i=1;i<=90;i++) f[i]=f[i-1]+f[i-2]; while(cin>>n>>m) { build(1,1,n); int op,k,d,l,r; while(m--) { scanf("%d",&op); if(op==1) { scanf("%d%d",&k,&d); setval(1,k,d); } else { scanf("%d%d",&l,&r); if(op==2) printf("%I64d\n",query(1,l,r)); else update(1,l,r); } } } return 0; }
不能直接一整个区间更新,因为有大量不必要的更新操作,算出每个点最多更新多少次,暴力单点
以上是关于HDU 4893 Wow! Such Sequence 线段树暴力的主要内容,如果未能解决你的问题,请参考以下文章