Codevs2492:上帝造题的七分钟 2(并查集)

来源:互联网 发布:相册加密软件 编辑:程序博客网 时间:2024/05/07 05:44

传送门

题意:
支持区间开方求和。

题解:
每一位数有效操作次数很少,所以并查集维护右边第一个不为1的数,暴力修改就好了。求和用树状数组。

#include<bits/stdc++.h>typedef long long ll;using namespace std;inline ll read(){    char ch=getchar();ll i=0,f=1;    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}    while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}    return (f==1)?i:-i;}inline void W(ll x){    static int buf[50];    if(!x){putchar('0');return;}    if(x<0){putchar('-');x=-x;}    while(x){buf[++buf[0]]=x%10;x/=10;}    while(buf[0])putchar(buf[buf[0]--]+'0');}const int Maxn=1e5+50;int n,r[Maxn];ll a[Maxn],bit[Maxn];inline int getr(int x){return (r[x]==x)?x:(r[x]=getr(r[x]));}inline void merge(int x,int y){    x=getr(x),y=getr(y);    (x==y)?(0):(r[x]=y);}inline void ins(int pos,ll x){    for(;pos<=n;pos+=(pos&(-pos)))bit[pos]+=x;}inline ll qry(int pos){    ll res=0;    for(;pos;pos-=(pos&(-pos)))res+=bit[pos];    return res;}int main(){    n=read();    for(int i=1;i<=n;i++)r[i]=i,a[i]=read(),ins(i,a[i]);    for(int i=read();i>=1;i--){        int op=read(),bg=read(),ed=read();        if(bg>ed)swap(bg,ed);        if(op==1){W(qry(ed)-qry(bg-1));putchar('\n');continue;}         for(int pos=bg;pos<=ed;pos=getr(pos)+1){            ll t=(ll)(sqrt(a[pos]));            if(t-a[pos])ins(pos,t-a[pos]);            a[pos]=t;            if(a[pos]==1&&pos-1)merge(pos-1,pos);        }    }}
阅读全文
0 0
原创粉丝点击