1. 程式人生 > >#38 遊戲(線段樹)

#38 遊戲(線段樹)

復雜度 max getc const return inf mes iostream lse

  註意到等級的變化最多有nm次。於是考慮比較暴力的做法,線段樹維護每個區間內每個等級角色的最大經驗值,區間加時看有沒有可以升級的,如果有則暴力向兩邊遞歸,否則打上標記。復雜度O(nmlogn)。

  似乎有更優的做法。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cassert>
using namespace std;
#define N 1000010 #define int long long #define inf 1000000000000000 int read() { int x=0,f=1;char c=getchar(); while (c<0||c>9) {if (c==-) f=-1;c=getchar();} while (c>=0&&c<=9) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,q,a[12],v[N]; struct data{int
L,R,lazy,sum,max[12]; }tree[N<<2]; int value(int x) { for (int i=1;i<=m;i++) if (a[i]>x) return i-1; } void up(int k) { for (int i=1;i<=m;i++) tree[k].max[i]=max(tree[k<<1].max[i],tree[k<<1|1].max[i]); tree[k].sum=tree[k<<1].sum+tree[k<<1|1
].sum; } void update(int k,int x) { if (tree[k].L==tree[k].R) { for (int i=1;i<=m;i++) if (tree[k].max[i]>=0) {x+=tree[k].max[i];tree[k].max[i]=-inf;break;} tree[k].max[(tree[k].sum=value(x))+1]=x; return; } for (int i=1;i<=m;i++) { tree[k].max[i]+=x; if (tree[k].max[i]>=a[i]) { x+=tree[k].lazy,tree[k].lazy=0; update(k<<1,x), update(k<<1|1,x); up(k); return; } } tree[k].lazy+=x; } void down(int k) { update(k<<1,tree[k].lazy); update(k<<1|1,tree[k].lazy); tree[k].lazy=0; } void build(int k,int l,int r) { tree[k].L=l,tree[k].R=r; for (int i=1;i<=m;i++) tree[k].max[i]=-inf; if (l==r) {tree[k].sum=value(v[l]),tree[k].max[value(v[l])+1]=v[l];return;} int mid=l+r>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); up(k); } void add(int k,int l,int r,int x) { if (tree[k].L==l&&tree[k].R==r) {update(k,x);return;} if (tree[k].lazy) down(k); int mid=tree[k].L+tree[k].R>>1; if (r<=mid) add(k<<1,l,r,x); else if (l>mid) add(k<<1|1,l,r,x); else add(k<<1,l,mid,x),add(k<<1|1,mid+1,r,x); up(k); } void modify(int k,int p,int x) { if (tree[k].L==tree[k].R) { for (int i=1;i<=m;i++) tree[k].max[i]=-inf; tree[k].max[(tree[k].sum=value(x))+1]=x; return; } if (tree[k].lazy) down(k); int mid=tree[k].L+tree[k].R>>1; if (p<=mid) modify(k<<1,p,x); else modify(k<<1|1,p,x); up(k); } int query(int k,int l,int r) { if (tree[k].L==l&&tree[k].R==r) return tree[k].sum; if (tree[k].lazy) down(k); int mid=tree[k].L+tree[k].R>>1; if (r<=mid) return query(k<<1,l,r); else if (l>mid) return query(k<<1|1,l,r); else return query(k<<1,l,mid)+query(k<<1|1,mid+1,r); } signed main() { #ifndef ONLINE_JUDGE freopen("c.in","r",stdin); freopen("c.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(),m=read(),q=read(); for (int i=1;i<=m;i++) a[i]=read();a[++m]=inf; for (int i=1;i<=n;i++) v[i]=read(); build(1,1,n); while (q--) { int op=read(); if (op==1) { int l=read(),r=read(),x=read(); add(1,l,r,x); } if (op==2) { int p=read(),x=read(); modify(1,p,x); } if (op==3) { int l=read(),r=read(); printf("%d\n",query(1,l,r)); } } return 0; }

#38 遊戲(線段樹)