「BZOJ3038」上帝造题的七分钟2
Description
XLk觉得《上帝造题的七分钟》不太过瘾,于是有了第二部。
“第一分钟,X说,要有数列,于是便给定了一个正整数数列。
第二分钟,L说,要能修改,于是便有了对一段数中每个数都开平方(下取整)的操作。
第三分钟,k说,要能查询,于是便有了求一段数的和的操作。
第四分钟,彩虹喵说,要是NOIP难度,于是便有了数据范围。
第五分钟,诗人说,要有韵律,于是便有了时间限制和内存限制。
第六分钟,和雪说,要省点事,于是便有了保证运算过程中及最终结果均不超过64位有符号整数类型的表示范围的限制。
第七分钟,这道题终于造完了,然而,造题的神牛们再也不想写这道题的程序了。”
——《上帝造题的七分钟·第二部》
所以这个神圣的任务就交给你了。
Input
第一行一个整数n,代表数列中数的个数。
第二行n个正整数,表示初始状态下数列中的数。
第三行一个整数m,表示有m次操作。
接下来m行每行三个整数k,l,r,k=0表示给[l,r]中的每个数开平方(下取整),k=1表示询问[l,r]中各个数的和。
Output
对于询问操作,每行输出一个回答。
Sample Input
1 2 3 4 5 6 7 8 9 10
5
0 1 10
1 1 10
1 1 5
0 5 8
1 4 8
Sample Output
7
6
HINT
1:对于100%的数据,1<=n<=100000,1<=l<=r<=n,数列中的数大于0,且不超过1e12。
2:数据不保证L<=R 若L>R,请自行交换L,R,谢谢!
代码
裸打似乎是40分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
#include<iostream> #include<cstdio> #include<cmath> using namespace std; int n,a[100001],m; struct data{ int l,r,sum; }tr[400001]; void build(int k,int s,int t) { tr[k].l=s;tr[k].r=t; if(s==t){ tr[k].sum=a[s]; return; } int mid=(s+t)>>1; build(k<<1,s,mid); build(k<<1|1,mid+1,t); tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum; } void change(int k,int x,int y) { int l=tr[k].l,r=tr[k].r; if(l==r){tr[k].sum=(int)sqrt(tr[k].sum);return;} int mid=(l+r)>>1; if(mid>=y)change(k<<1,x,y); else if(mid<x)change(k<<1|1,x,y); else { change(k<<1,x,mid); change(k<<1|1,mid+1,y); } tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum; } int ask(int k,int x,int y) { int l=tr[k].l,r=tr[k].r; if(l==x&&r==y)return tr[k].sum; int mid=(l+r)>>1; if(mid>=y)return ask(k<<1,x,y); else if(mid<x)return ask(k<<1|1,x,y); else return ask(k<<1,x,mid)+ask(k<<1|1,mid+1,y); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); build(1,1,n); scanf("%d",&m); for(int i=1;i<=m;i++) { int k,x,y; scanf("%d%d%d",&k,&x,&y); if(x>y)swap(x,y); if(k==0)change(1,x,y); else printf("%d\n",ask(1,x,y)); } return 0; } |
加了优化死活50分
后来发现我没开long long
….
优化就是如果一个结点值为0或者1就不再更新;
如果一棵树左右儿子都不再更新,它也不再更新
670s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
#include<iostream> #include<cstdio> #include<cmath> #define ll long long using namespace std; ll a[100001];int n,m; struct data{ int l,r;ll sum; bool flag; }tr[400001]; void build(int k,int s,int t) { tr[k].l=s;tr[k].r=t; if(s==t){ tr[k].sum=a[s]; if(a[s]==1||a[s]==0)tr[k].flag=1; return; } int mid=(s+t)>>1; build(k<<1,s,mid); build(k<<1|1,mid+1,t); tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum; tr[k].flag=tr[k<<1].flag&tr[k<<1|1].flag; } void change(int k,int x,int y) { if(tr[k].flag)return; int l=tr[k].l,r=tr[k].r; if(l==r){ tr[k].sum=(ll)sqrt(tr[k].sum); if(tr[k].sum==1||tr[k].sum==0)tr[k].flag=1; return; } int mid=(l+r)>>1; if(mid>=y)change(k<<1,x,y); else if(mid<x)change(k<<1|1,x,y); else { change(k<<1,x,mid); change(k<<1|1,mid+1,y); } tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum; tr[k].flag=tr[k<<1].flag&tr[k<<1|1].flag; } ll ask(int k,int x,int y) { int l=tr[k].l,r=tr[k].r; if(l==x&&r==y)return tr[k].sum; int mid=(l+r)>>1; if(mid>=y)return ask(k<<1,x,y); else if(mid<x)return ask(k<<1|1,x,y); else return ask(k<<1,x,mid)+ask(k<<1|1,mid+1,y); } int main() { scanf("%d",&n); for(int i=1;i<=n;i++)scanf("%lld",&a[i]); build(1,1,n); scanf("%d",&m); for(int i=1;i<=m;i++) { int k,x,y; scanf("%d%d%d",&k,&x,&y); if(x>y)swap(x,y); if(!k)change(1,x,y); else printf("%lld\n",ask(1,x,y)); } return 0; } |
好像这是传说中的快速读入么。。530s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
#include<iostream> #include<cstdio> #include<cmath> #define check(ch) (ch>='0'&&ch<='9') #define ll long long using namespace std; ll n,a[100001],m; struct data{ int l,r;ll sum; bool flag; }tr[400001]; void getint(ll &t ){ int ch; for(ch=getchar( );!check(ch);ch=getchar( )); t=ch-'0'; for(ch=getchar( );check(ch);ch=getchar( ))t*=10,t+=ch-'0'; } void putint(ll t){ int ans[40]={0}; for(;t;t/=10)ans[++ans[0]]=t%10; for(;ans[0];ans[0]--)putchar('0'+ans[ans[0]]); putchar('\n'); } void build(int k,int s,int t) { tr[k].l=s;tr[k].r=t; if(s==t){ tr[k].sum=a[s]; if(a[s]==1||a[s]==0)tr[k].flag=1; return; } int mid=(s+t)>>1; build(k<<1,s,mid); build(k<<1|1,mid+1,t); tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum; tr[k].flag=tr[k<<1].flag&tr[k<<1|1].flag; } void change(int k,int x,int y) { if(tr[k].flag)return; int l=tr[k].l,r=tr[k].r; if(l==r){ tr[k].sum=(ll)sqrt(tr[k].sum); if(tr[k].sum==1||tr[k].sum==0)tr[k].flag=1; return; } int mid=(l+r)>>1; if(mid>=y)change(k<<1,x,y); else if(mid<x)change(k<<1|1,x,y); else { change(k<<1,x,mid); change(k<<1|1,mid+1,y); } tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum; tr[k].flag=tr[k<<1].flag&tr[k<<1|1].flag; } ll ask(int k,int x,int y) { int l=tr[k].l,r=tr[k].r; if(l==x&&r==y)return tr[k].sum; int mid=(l+r)>>1; if(mid>=y)return ask(k<<1,x,y); else if(mid<x)return ask(k<<1|1,x,y); else return ask(k<<1,x,mid)+ask(k<<1|1,mid+1,y); } int main() { getint(n); for(int i=1;i<=n;i++)getint(a[i]); build(1,1,n); getint(m); for(int i=1;i<=m;i++) { ll k,x,y; getint(k);getint(x);getint(y); if(x>y)swap(x,y); if(!k)change(1,x,y); else putint(ask(1,x,y)); } return 0; } |