2012 ACM/ICPC Asia Regional Changchun Online A Simple Problem with Integers

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/syh0313/article/details/88045527

动态开点线段树:

因为一开始想的是开k课线段树,但是发现它其实求的是相对于a的位置,而不是相对于1的位置,所以开k棵线段树无法将信息存完全

那么我们考虑为什么信息会丢失,是因为i%mo(1=<mo<=10)有mo个,所以我们也要将这些信息记录下来,那么总的信息个数就是

10+9+....+1=55个。所以我们开55棵线段树维护一下就好了。

这里建线段树用动态开点(有dalao学长直接用55棵线段树过了orz)

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#define lch a[n].lc
#define rch a[n].rc
using namespace std;
const int maxn=50010;
struct data {int rc,lc;long long ad;}a[220*maxn];
int nn,m,topt,root[11][12];
long long v[maxn];
void pushdown(int n)
{
    if (a[n].ad) 
    {
        if (!lch) lch=++topt; a[lch].ad+=a[n].ad; 
        if (!rch) rch=++topt; a[rch].ad+=a[n].ad; 
        a[n].ad=0;
    }
}
void tree_add(int &n,int L,int R,int l,int r,long long k)
{
    if (!n) n=++topt;
    if (L==l && R==r) {a[n].ad+=k; return;}
    pushdown(n); int mid=(L+R)>>1;
    if (r<=mid) tree_add(lch,L,mid,l,r,k);
    else if (l>=mid+1) tree_add(rch,mid+1,R,l,r,k);
    else tree_add(lch,L,mid,l,mid,k),tree_add(rch,mid+1,R,mid+1,r,k);
}
long long qury(int &n,int l,int r,int lc)
{
    if (!n) n=++topt;
    if (l==r && r==lc) return a[n].ad;
    pushdown(n); int mid=(l+r)>>1;
    if (lc<=mid) return qury(lch,l,mid,lc);
     else return qury(rch,mid+1,r,lc);
}
int main()
{
    while (~scanf("%d",&nn))
    {
        for (int i=1;i<=topt;i++) a[i].ad=a[i].lc=a[i].rc=0;
        memset(root,0,sizeof root); topt=0; 
        for (int i=1;i<=nn;i++) scanf("%lld",&v[i]); 
        scanf("%d",&m);
        while (m--)
        {
            int ff; scanf("%d",&ff);
            if (ff==1)
            {
                int xx,yy,k; long long c;
                scanf("%d%d%d%lld",&xx,&yy,&k,&c); int mo=xx%k;
                tree_add(root[xx%k][k],0,nn/k,(xx-mo)/k,(yy-mo)/k,c);
            }
            else 
            {
                int lc; long long ans=0; scanf("%d",&lc);
                for (int i=0;i<10;i++)
                  for (int j=1;j<=10;j++)
                   if (lc%j==i && root[i][j]) 
                    ans+=qury(root[i][j],0,nn/j,(lc-i)/j);
                 printf("%lld\n",ans+v[lc]);
            }
        }
    }
return 0;
}

猜你喜欢

转载自blog.csdn.net/syh0313/article/details/88045527