题目链接:https://www.spoj.pl/problems/GSS4/
题目大意:求和+更新,一看到这种组合再看数据(n<=100,000)就忍不住想到到线段树.更新是把某段区间的值该为其平方根后的值(保留整数部分,但是题目写的是四舍五入的意思).
思路:看着像区间更新,但是每一点每次减少的值不一定一样,所以lazy标志不怎么适用.其实这题看似区间更新,其实是单点更新,因为序列中最大的值不会超过10^18,所以每一个值最多被更新7次,所以复杂度还是O(nlogn).
代码:
#include <stdlib.h> #include <string.h> #include <stdio.h> #include <ctype.h> #include <math.h> #include <time.h> #include <stack> #include <queue> #include <map> #include <set> #include <vector> #include <string> #include <iostream> #include <algorithm> using namespace std; //#define ull unsigned __int64 //#define ll __int64 #define ull unsigned long long #define ll long long #define son1 New(p.xl,xm,p.yl,ym),(rt<<2)-2 #define son2 New(p.xl,xm,min(ym+1,p.yr),p.yr),(rt<<2)-1 #define son3 New(min(xm+1,p.xr),p.xr,p.yl,ym),rt<<2 #define son4 New(min(xm+1,p.xr),p.xr,min(ym+1,p.yr),p.yr),rt<<2|1 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define middle (l+r)>>1 #define MOD 1000000007 #define esp (1e-8) const int INF=0x3F3F3F3F; const double DINF=10000.00; //const double pi=acos(-1.0); const int N=100010; int n,m,tot=0,k; ll mmax[N<<2],sum[N<<2]; ll max(ll x,ll y){return x>y? x:y;} void swap(ll x,ll y){ll t=x;x=y;y=t;} void pushUp(int rt){ int ls=rt<<1,rs=ls|1; sum[rt]=sum[ls]+sum[rs]; mmax[rt]=max(mmax[ls],mmax[rs]); } void build(int l,int r,int rt){ if(l==r){ scanf("%lld",&mmax[rt]); sum[rt]=mmax[rt]; return; } int mid=middle; build(lson),build(rson); pushUp(rt); } void modify(int l,int r,int rt){ if(l==r){ sum[rt]=mmax[rt]=(ll)sqrt(1.0*mmax[rt]); return; } int mid=middle; if(mmax[rt<<1]>1) modify(lson); if(mmax[rt<<1|1]>1) modify(rson); pushUp(rt); } void update(int l,int r,int rt,int L,int R){ if(L<=l && r<=R){ if(mmax[rt]>1) modify(l,r,rt); return; } int mid=middle; if(L<=mid) update(lson,L,R); if(mid<R) update(rson,L,R); pushUp(rt); } ll query(int l,int r,int rt,int L,int R){ if(L<=l & r<=R) return sum[rt]; int mid=middle; ll ret=0; if(L<=mid) ret+=query(lson,L,R); if(mid<R) ret+=query(rson,L,R); return ret; } void init(){ build(1,n,1); scanf("%d",&m); } void sof(){ int op,x,y; printf("Case #%d:\n",++tot); while(m--){ scanf("%d%d%d",&op,&x,&y); if(x>y) swap(x,y); if(op) printf("%lld\n",query(1,n,1,x,y)); else update(1,n,1,x,y); }puts(""); } int main(){ //freopen("1.in","r",stdin); //freopen("1.out","w",stdout); //int T,cas;scanf("%d",&T);for(cas=1;cas<=T;cas++) init(),sof(); while(~scanf("%d",&n)) init(),sof(); //init(),sof(); return 0; }