211: 花神游历各国
Time Limit: 5 Sec Memory Limit: 128 MB
Submit: 1695 Solved: 646
[Submit][Status][Discuss]
Description
Input
Output
每次x=1时,每行一个整数,表示这次旅行的开心度
Sample Input
4
1 100 5 5
5
1 1 2
2 1 2
1 1 2
2 2 3
1 1 4
Sample Output
101
11
11
HINT
对于100%的数据, n ≤ 100000,m≤200000 ,data[i]非负且小于10^9
一开始想用树状数组理想秒A,但是树状数组不支持区间开根修改,于是用并查集优化,因为10的9次方最多开方5次就变成1,所以f[i]表示>=i的第一个不为1的数的编号。
for (i=find(l);i<=r;i=find(i+1))
如果开根到1以下,需要更改f[i]
if (a[i]<=1) f[i]=find(i+1);
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
long long n,i,t,x,y,z,m,j,k,a[100001],f[100002],c[100001];;
long long lowbit(int x)
{
return x&(-x);
}
void add(int loc,int value)
{
int j;
for (j=loc;j<=n;j+=lowbit(j))
c[j]+=value;
}
long long query(int loc)
{
int j;
long long ans=0;
for (j=loc;j>=1;j-=lowbit(j))
ans+=c[j];
return ans;
}
long long find(int x)
{
if (x==f[x])
return x;
else
{
f[x]=find(f[x]);
return f[x];
}
}
int main()
{
scanf("%lld",&n);
for (i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
add(i,a[i]);
f[i]=i;
}
f[n+1]=n+1;
scanf("%lld",&m);
for (i=1;i<=m;i++)
{
scanf("%lld %lld %lld",&x,&y,&z);
if (x==1)
printf("%lld\n",query(z)-query(y-1));
if (x==2)
for (k=find(y);k<=z;k=find(k+1))
{
t=int(sqrt(a[k]));
add(k,t-a[k]);
a[k]=t;
if (a[k]<=1)
f[k]=find(k+1);
}
}
return 0;
}
一开始一直RE,后又Time Limit Exceed,然后又Wrong Answer,我太弱了,一天不跪(DaD3zZ,Yveh,Shallwe,xiaoyimi,稷,DMonster)浑身难受。。。