3211: 花神游历各国
Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 3311 Solved: 1227
[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
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
11
11
今天alone_wolf又在讲线段树啦
作为例题之一我查了题解。。。
因为对于每个数最多O(nloglogn)次不会再改变(变成0 or 1)
所以。。一顿乱搞
哦,对了,不要忘记最后一个数会指向区间之外,做一下标记要不会死循环。。。
PS: 3038比较坑。。看看题。。鬼畜WA两发
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
inline ll read()
{
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int N=100100;
int n,fa[N];
ll c[N],a[N];
inline int find(int x)
{
int t=x;
while(t!=fa[t])t=fa[t];
while(x!=fa[x])x=fa[x],fa[x]=t;
return x;
}
inline void update(int x,ll val)
{for(;x<=n;x+=(x&-x))c[x]+=val;}
inline void modify(int x,int y)
{
for(int i=x;i<=y;i=find(i+1))
{
ll t=floor(sqrt(a[i]));
update(i,t-a[i]);a[i]=t;
if(a[i]<=1)fa[i]=find(i+1);
}
}
inline void query(int x,int y)
{
ll sum=0;
for(;y;y-=(y&-y))sum+=c[y];
for(;x;x-=(x&-x))sum-=c[x];
printf("%lld\n",sum);
}
int main()
{
n=read();
for(int i=1;i<=n;i++){a[i]=read(),fa[i]=i,update(i,a[i]);if(a[i]<=1)fa[i]=i+1;}fa[n+1]=n+1;
int m=read();
while(m--)
{
int opt=read(),x=read(),y=read();if(x>y)swap(x,y);
if(opt==1){query(x-1,y);}
else {modify(x,y);}
}
return 0;
}
/*
4
1 100 5 5
5
1 1 2
2 1 2
1 1 2
2 2 3
1 1 4
101
11
11
*/