您的位置:首页 > 其它

bzoj3211花神游历各国

2017-10-31 19:45 225 查看
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

Source

SPOJ2713 gss4 数据已加强

看了好几道并查集的题都不会都说是和这道题一模一样

那么我们来看看这道题把。

首先可以用线段树暴力做复杂度大概多个log

线段树做就是暴力做法吧

我们来学习一下树状数组加并查集的更暴力的做法吧

思路是暴力修改l到r然后用并查集跳过那些已经不能继续开方的数

大概基本很多人的修改都是下面的这一句话

for(int j=l;j<=r;add(j,(t=(int)sqrt(a[j]))-a[j]),a[j]=t,
f[j]=(a[j]<=1)?j+1:j,j=(find(j)==j?j+1:f[j]));


!这种东西我能看懂么

不存在的

不过好像第一行就是暴力修改的意思没啥可想的

如果j已经被削到1以下(开方没变化),那么原来连向j的那些应该指向j+1了,否则还指向j

第二句表示如果j还指向自己那么就一位一位走,否则直接从父亲转移。

对于正确性我觉得随便手玩一下就懂了

那么我们学会了新知识!!!

虽然只是能看懂自己根本写不出来

#include<cstdio>
#include<cstring>
#include<utility>
#include<algorithm>
#include<iostream>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdlib>
#include<ctime>
using namespace std;
inline int read()
{
char ch='*';
int f=1;
while(!isdigit(ch=getchar())) if(ch=='-') f=-1;
int num=ch-'0';
while(isdigit(ch=getchar())) num=num*10+ch-'0';
return num*f;
}
typedef long long ll;
const int maxn = 100005;
ll c[maxn];
int a[maxn],f[maxn],n,m,op,l,r,t;
int find(int x){return x==f[x]? x:f[x]=find(f[x]);}
inline void add(int x ,int num) {while(x<=n) c[x]+=num,x+=x&-x;}
inline ll sum(int x){ll s = 0;while(x) s+=c[x],x-=x&-x;return s;}
int main()
{
n=read();
for(register int i=1;i<=n;i++) f[i]=i,a[i]=read(),add(i,a[i]);
m=read();f[n+1]=n+1;
for(register int i=1;i<=m;i++)
{
op=read();l=read();r=read();
if(op==1){
printf("%lld\n",(sum(r)-sum(l-1)));
}
else for(int j=l;j<=r;add(j,(t=(int)sqrt(a[j]))-a[j]),a[j]=t, f[j]=(a[j]<=1)?j+1:j,j=(find(j)==j?j+1:f[j]));
}
return 0;
}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: