BZOJ3211花神游历各国

211: 花神游历各国

Time Limit: 5 Sec Memory Limit: 128 MB
Submit: 1695 Solved: 646
[Submit][Status][Discuss]
Description
BZOJ3211花神游历各国_第1张图片
Input
BZOJ3211花神游历各国_第2张图片
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
#include
#include
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)浑身难受。。。

你可能感兴趣的:(并查集,树状数组)