NC236242 序列求和
题目链接
关键点:
1、利用开根号的性质,一个数在开有限次根号后就会变成1,利用这个性质,当该数开根号为1时,就不要再进行开根号了。
2、big标记表示当前区间是否全开为1,所以big区间更新取左右区间的最大值,如果为1,说明左右区间均全开为1
3、数据范围开long long
完整代码:
# include <iostream>
# include <cstdio>
# include <cmath>
# include <algorithm>
typedef long long ll;
using namespace std;
const int N = 2e6+10;
struct ty{
int l, r;
ll sum, big;
}tree[N*4];
int n, q;
int a[N];
void build (int p, int l, int r)
{
if (l == r)
{
tree[p].sum = a[l];
tree[p].l = tree[p].r = l;
tree[p].big = a[l];
return ;
}
else
{
tree[p].l = l;
tree[p].r = r;
int mid = (l+r)/2;
build(p*2, l, mid);
build(p*2+1, mid+1, r);
tree[p].sum = tree[p*2].sum + tree[p*2+1].sum;
tree[p].big = max(tree[p*2].big, tree[p*2+1].big);
}
}
void change(int p, int l, int r)
{
if (tree[p].l == tree[p].r)
{
tree[p].sum = sqrt(tree[p].sum);
tree[p].big = tree[p].sum;
return ;
}
else
{
int mid = (tree[p].l + tree[p].r)/2;
if (l<=mid && tree[p*2].big > 1) change(2*p, l, r);
if (r>mid && tree[p*2+1].big > 1) change(2*p+1, l, r);
tree[p].sum = tree[p*2].sum + tree[p*2+1].sum;
tree[p].big = max(tree[p*2].big, tree[p*2+1].big);
}
}
ll calc(int p, int l, int r)
{
if (l <= tree[p].l && r >= tree[p].r)
{
return tree[p].sum;
}
else
{
int mid = (tree[p].l + tree[p].r)/2;
ll ans = 0;
if (l<=mid) ans += calc(p*2, l, r);
if (r>mid) ans += calc(p*2+1, l, r);
return ans;
}
}
int main()
{
cin>>n>>q;
for (int i=1; i<=n; i++)
cin>>a[i];
build(1,1,n);
for (int i=1; i<=q; i++)
{
int x;
cin>>x;
if (x == 1)
{
int l, r;
cin>>l>>r;
change(1, l, r);
}
else if (x == 2)
{
int l, r;
cin>>l>>r;
cout<<calc(1, l, r)<<endl;
}
}
return 0;
}
NC50428 数星星 Stars
题目链接
关键点:
1、因为题目给出的星星顺序是按照y从小到大,x从小到大,在0-maxx(x)中开线段树,对于当前x,看小于等于x区间内是否出现星星,即为该星星的等级数量。
2、对于当前输入的x,先查询[0, x]内星星的个数,然后记上该星星的等级,然后再在线段树的x位置+1,加上当前星星
完整代码:
# include <bits/stdc++.h>
using namespace std;
const int N = 4e5+10;
typedef long long ll;
struct ty{
int l, r;
ll sum;
}tree[N*4];
ll n, maxx;
ll a[N], ans[N];
void build(int p, int l, int r)
{
if (l == r)
{
tree[p].l = tree[p].r = l;
tree[p].sum = 0;
return ;
}
tree[p].l = l;
tree[p].r = r;
int mid = (l+r)/2;
build(2*p, l, mid);
build(2*p+1, mid+1, r);
// tree[p].sum = tree[p*2].sum + tree[p*2+1].sum;
}
int calc(int p, int l, int r)
{
if (l<=tree[p].l && r>=tree[p].r)
{
return tree[p].sum;
}
int mid = (tree[p].l + tree[p].r)/2;
int ans = 0;
if (l<=mid) ans += calc(p*2, l, r);
if (r>mid) ans += calc(p*2+1, l, r);
return ans;
}
void change(int p, int x)//在x位置加1
{
if (tree[p].l == tree[p].r)
{
tree[p].sum ++;
return ;
}
int mid = (tree[p].l + tree[p].r)/2;
if (x<=mid) change(p*2, x);
else change(p*2+1, x);
tree[p].sum = tree[p*2].sum + tree[p*2+1].sum;
}
int main()
{
cin>>n;
build(1, 0, N);
for (int i=1; i<=n; i++)
{
int x, y;
cin>>x>>y;
int s = calc(1, 0, x);
ans[s]++;
change(1, x);
}
for (int i=0; i<n; i++)
cout<<ans[i]<<endl;
return 0;
}