codevs2492 上帝造题的七分钟 2
来源:互联网 发布:应用程序的端口号干什 编辑:程序博客网 时间:2024/04/30 06:12
题目描述 Description
XLk觉得《上帝造题的七分钟》不太过瘾,于是有了第二部。
"第一分钟,X说,要有数列,于是便给定了一个正整数数列。
第二分钟,L说,要能修改,于是便有了对一段数中每个数都开平方(下取整)的操作。
第三分钟,k说,要能查询,于是便有了求一段数的和的操作。
第四分钟,彩虹喵说,要是noip难度,于是便有了数据范围。
第五分钟,诗人说,要有韵律,于是便有了时间限制和内存限制。
第六分钟,和雪说,要省点事,于是便有了保证运算过程中及最终结果均不超过64位有符号整数类型的表示范围的限制。
第七分钟,这道题终于造完了,然而,造题的神牛们再也不想写这道题的程序了。"
——《上帝造题的七分钟·第二部》
所以这个神圣的任务就交给你了。
输入描述 Input Description
第一行一个整数n,代表数列中数的个数。
第二行n个正整数,表示初始状态下数列中的数。
第三行一个整数m,表示有m次操作。
接下来m行每行三个整数k,l,r,k=0表示给[l,r]中的每个数开平方(下取整),k=1表示询问[l,r]中各个数的和。
UPD:注意数据中有可能l>r,所以遇到这种情况请交换l和r。
输出描述 Output Description
对于询问操作,每行输出一个回答。
样例输入 Sample Input
10
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
19
7
6
数据范围及提示 Data Size & Hint
对于30%的数据,1<=n,m<=1000,数列中的数不超过32767。
对于100%的数据,1<=n,m<=100000,1<=l,r<=n,数列中的数大于0,且不超过1e12。
注意l有可能大于r,遇到这种情况请交换l,r。
来源:Nescafe 20
【思路】
区间查询+打标记。
一个关键的思想就是一个数被反复开方并向下取整最终会变为1,如果一个数变成1就不需要对它操作了。
对于区间开方操作,对于区间中的每一个点都进行操作如果为1则下次不再操作。
实现1:
BIT+“并查集”。
【代码1】
1 //341ms 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 7 using namespace std; 8 9 typedef long long LL;10 const int maxn = 200000+10;11 12 LL a[maxn],p[maxn];13 int n,m;14 15 LL read() {16 char c=getchar();17 while(!isdigit(c)) c=getchar();18 LL x=0;19 while(isdigit(c)) {20 x=x*10+c-'0';21 c=getchar();22 }23 return x;24 }25 26 LL c[maxn];27 int lowbit(int x) { return x&(-x); }28 LL Sum(LL x) {29 LL res=0;30 while(x>0) {31 res += c[x];32 x-=lowbit(x);33 }34 return res;35 }36 void Add(int x,LL d) {37 while(x<=n) {38 c[x] += d;39 x += lowbit(x);40 }41 }42 int find(int x) {43 return x==p[x]?x:p[x]=find(p[x]);44 }45 46 int main() {47 n=read();48 FOR(i,1,n) a[i]=read(),Add(i,a[i]);49 FOR(i,1,n+1) p[i]=i; //n+1为哨兵 50 m=read();51 LL u,v,w;52 FOR(i,1,m) {53 w=read(),u=read(),v=read();54 if(u>v) swap(u,v);55 56 if(w)57 printf("%lld\n",Sum(v)-Sum(u-1));58 else 59 {60 for(int j=find(u);j<=v;j=find(j+1)) {61 LL s=sqrt(a[j]);62 Add(j,s-a[j]);63 a[j]=s;64 if(s==1) {65 p[j]=j+1;66 if(j==v) break;67 }68 }69 }70 }71 return 0;72 }
实现2:
线段树+结点标记
【代码2】
1 //399ms 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 7 using namespace std; 8 9 typedef long long LL;10 const int maxn = 500000+10;11 12 LL a[maxn],p[maxn];13 int n,m;14 15 LL read() {16 char c=getchar();17 while(!isdigit(c)) c=getchar();18 LL x=0;19 while(isdigit(c)) {20 x=x*10+c-'0';21 c=getchar();22 }23 return x;24 }25 26 LL sumv[maxn];27 bool f[maxn];28 void build(int u,int L,int R) {29 int lc=u*2,rc=u*2+1;30 if(L==R) {31 sumv[u]=a[L];32 }33 else {34 int M=L+(R-L)/2;35 build(lc,L,M);36 build(rc,M+1,R);37 sumv[u]=sumv[lc]+sumv[rc];38 }39 }40 int ya,yb;41 void update(int u,int L,int R) {42 int lc=u*2,rc=u*2+1;43 if(f[u]) return ;44 if(L==R) {45 sumv[u]=sqrt(sumv[u]);46 if(sumv[u]==1) f[u]=1;47 }48 else {49 int M=L+(R-L)/2;50 if(ya<=M) update(lc,L,M);51 if(M<yb) update(rc,M+1,R);52 53 sumv[u]=sumv[lc]+sumv[rc];54 f[u]=f[lc]&&f[rc];55 }56 }57 LL query(int u,int L,int R) {58 int lc=u*2,rc=u*2+1;59 if(ya<=L && R<=yb) {60 return sumv[u];61 }62 else {63 int M=L+(R-L)/2;64 LL res=0;65 if(ya<=M) res+=query(lc,L,M);66 if(M<yb) res+=query(rc,M+1,R);67 return res;68 }69 }70 71 int main() {72 n=read();73 FOR(i,1,n) a[i]=read();74 build(1,1,n);75 m=read();76 int w;77 while(m--) {78 w=read(),ya=read(),yb=read();79 if(ya>yb) swap(ya,yb);80 if(w) printf("%lld\n",query(1,1,n));81 else update(1,1,n);82 }83 return 0;84 }
- 【BZOJ3038】【Codevs2492】上帝造题的七分钟2
- codevs2492 上帝造题的七分钟 2
- 【codevs2492】【Tyvj1941】上帝造题的七分钟2,线段树的特别技巧
- codevs2492 上帝造题的七分钟2 BZOJ3211 花神游历各国
- CodeVS2492 上帝造题的七分钟2(树状数组+并查集)
- Codevs2492:上帝造题的七分钟 2(并查集)
- [BZOJ3132] 上帝造题的七分钟
- 【BZOJ3132】上帝造题的七分钟
- [BZOJ3132]上帝造题的七分钟
- BZOJ3132上帝造题的七分钟
- 【bzoj3132】上帝造题的七分钟
- 【BZOJ3132】上帝造题的七分钟
- 【bzoj3038】 上帝造题的七分钟2
- [BZOJ3038][线段树]上帝造题的七分钟2
- bzoj3038 上帝造题的七分钟2
- BZOJ 3038: 上帝造题的七分钟2
- BZOJ3038上帝造题的七分钟2
- [BZOJ3038]上帝造题的七分钟2
- NOI题库2454 雷涛的小猫
- 1017. A除以B
- 递归求解
- NOI题库1799 最短前缀
- NOIP2015 普及组(Junior) 解题报告
- codevs2492 上帝造题的七分钟 2
- Ubuntu 14.04 文件服务器--samba的安装和配置
- bzoj3192 [JLOI2013]删除物品
- 1018. 锤子剪刀布
- bzoj1227 [SDOI2009]虔诚的墓主人(组合公式+离散化+线段树)
- 设计Qt风格的C++API
- bzoj2124 等差子序列(hash+线段树)
- 递归求最大公约数
- HDU1251 统计难题(Trie)