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 */