每次x=1时,每行一个整数,表示这次旅行的开心度
对于100%的数据, n ≤ 100000,m≤200000 ,data[i]非负且小于10^9
SPOJ2713 gss4 数据已加强
思路:线段树并不能区间开方,但直接暴力修改是会超时的,只要加入一点点优化:若是该区间值为0||1那么就不必再修改了,注意也需要左右子树得出父节点。
上帝造题的七分钟2:不保证l<r,然后再加上读入和输出优化,还有开!long!long!少开long long 弄得我百思不得其解。
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #define MAXN 100000 using namespace std; long long lazy[MAXN*5],a[MAXN],b[MAXN*5]; long long segtree[MAXN*5]; int n,m; long long getin() { char ch = getchar(); long long data = 0; while (ch < '0' || ch > '9') ch = getchar(); do { data = data*10 + ch-'0'; ch = getchar(); } while (ch >= '0' && ch <= '9'); return data; } void putout(long long t){ long long ans[40]={0},i=0; for(;t;t/=10) ans[++i]=t%10; for(;i;i--) putchar('0'+ans[i]); putchar('\n'); } void adddata(int now) { segtree[now]=segtree[(now<<1)]+segtree[(now<<1)+1]; } void buildtree(int now,int l,int r) { if (l==r) {segtree[now]=a[l]; if (segtree[now]==1 || segtree[now]==0) b[now]=1; return;} int mid=(l+r)>>1; buildtree((now<<1),l,mid); buildtree((now<<1)+1,mid+1,r); adddata(now); b[now]=b[(now<<1)]&b[(now<<1)+1]; } long long query(int now,int l,int r,int begin,int end) { if (begin<=l && end>=r) return segtree[now]; long long mid=(l+r)>>1,ans=0; if (begin<=mid) ans+=query((now<<1),l,mid,begin,end); if (end>mid) ans+=query((now<<1)+1,mid+1,r,begin,end); return ans; } void intchange(int now,int l,int r,int begin,int end) { if (b[now]==1) return; if (l==r) {segtree[now]=floor(sqrt(segtree[now])); if (segtree[now]==1 || segtree[now]==0) b[now]=1; return;} int mid=(l+r)>>1; if (begin<=mid) intchange((now<<1),l,mid,begin,end); if (end>mid) intchange((now<<1)+1,mid+1,r,begin,end); adddata(now); b[now]=b[(now<<1)]&b[(now<<1)+1]; } int main() { int i; long long x,y,z; n=getin(); for (i=1;i<=n;i++) a[i]=getin(); buildtree(1,1,n); m=getin(); for (i=1;i<=m;i++) { x=getin(); y=getin(); z=getin(); if (y>z) swap(y,z); if (x==1) putout(query(1,1,n,y,z)); else intchange(1,1,n,y,z); } return 0; }