标签:return query col print \n 链接 min 更新 color
链接:
https://loj.ac/problem/6281
思路:
因为是向下取整开方,那么其实每个数最多被开个个几次就会变成0或者1了,更新的时候我们可以将中间的块标记下是否全部变成了0或者1,如果全变了就不处理
实现代码:
#include<bits/stdc++.h> using namespace std; #define ll long long const int M = 1e5 + 10; vector<int>v[M]; int a[M],block,n; int sum[M]; int tag[M]; int bl[M]; void reset(int x){ if(tag[x]) return; tag[x] = 1; sum[x] = 0; for(int i = (x-1)*block+1;i <= min(x*block,n);i ++){ a[i] = sqrt(a[i]); sum[x] += a[i]; if(a[i] > 1) tag[x] = 0; } } void update(int l,int r){ for(int i = l;i <= min(bl[l]*block,r);i ++){ sum[bl[l]] -= a[i]; a[i] = sqrt(a[i]); sum[bl[l]] += a[i]; } if(bl[l] != bl[r]){ for(int i = (bl[r]-1)*block+1;i <= r;i ++){ sum[bl[r]] -= a[i]; a[i] = sqrt(a[i]); sum[bl[r]] += a[i]; } } for(int i = bl[l] + 1;i <= bl[r] - 1;i ++){ reset(i); } } int query(int l,int r){ int ans = 0; for(int i = l;i <= min(bl[l]*block,r);i ++) ans += a[i]; if(bl[l] != bl[r]){ for(int i = (bl[r]-1)*block+1;i <= r;i ++) ans += a[i]; } for(int i = bl[l] + 1;i <= bl[r]-1;i ++) ans += sum[i]; return ans; } int main() { int l,r,opt,c; scanf("%d",&n); block = sqrt(n); for(int i = 1;i <= n;i ++){ scanf("%d",&a[i]); } for(int i = 1;i <= n;i ++){ bl[i] = (i - 1)/block + 1; sum[bl[i]] += a[i]; } for(int i = 1;i <= n;i ++){ scanf("%d%d%d%d",&opt,&l,&r,&c); if(opt == 0) update(l,r); else printf("%d\n",query(l,r)); } return 0; }
标签:return query col print \n 链接 min 更新 color
原文地址:https://www.cnblogs.com/kls123/p/9372893.html