洛谷 P3948 数据结构

传送门:洛谷 P3948 数据结构
题目描述:

维护一个数组,使其能区间修改,并动态查询某区间内满足\(min\leq(a_i\times i\ \%\ mod)\leq max\) 的数的个数


算法分析:该题操作共两个阶段——
1、在线:要求动态修改,但数据量很小(\(\leq 1000\)),可以暴力查询,区间修改,单点查询
2、离线:不要求动态修改,但数据量很大(\(\leq 10000000\)),可以预处理,然后区间查询
如上,跑两个树状数组即可。
事实证明,树状数组只能得72分,为了用数据结构(正解不用树状结构),吸个氧就过了(最大点490ms)


#include<iostream>
#include<cstdio>
#include<cstring>
#define node int
#define maxN 80000
#define in(x) x=read()
using namespace std;
class binary_tree
{
    public:
        inline node query(int x,int y) {return (y+1)*sum(tree1,y)-sum(tree2,y)-x*sum(tree1,x-1)+sum(tree2,x-1);}
        inline void build(node a[]) {for(register int i=1;i<=tot;i++) modify(i,a[i]-a[i-1]);}
        inline void update(node x,node y,node k) {modify(x,k); modify(y+1,-k);}
        inline void clear(int n) {tot=n; memset(tree1,0,sizeof(tree1)); memset(tree2,0,sizeof(tree2));}
    private:
        node tree1[maxN+1],tree2[maxN+1],tot;
        inline node lowbit(node x) {return x&(-x);}
        inline node sum(node a[],node x) {node ans=0; while(x>0) {ans+=a[x]; x-=lowbit(x);} return ans;}
        inline void modify(node x,node k) {for(register node i=x;i<=tot;i+=lowbit(i)) {tree1[i]+=k; tree2[i]+=k*x;}}
};
typedef int ll;
ll l,r,k,read(); char s[2];
int n,m,D,minT,maxT,check(int);
binary_tree treeA,treeB;
inline void task1(),task2();
int main()
{
    task1(); task2();
    return 0;
}
inline int check(int x)
{
    ll now=treeA.query(x,x)%D;
    if(minT<=((x*now)%D) && ((x*now)%D)<=maxT) return 1;
    return 0;
}
inline void task1()
{
    in(n); in(m); in(D); in(minT); in(maxT);
    treeA.clear(n);
    for(register int i=1;i<=m;i++)
    {
        scanf("%s",s); in(l); in(r);
        if(s[0]=='A') treeA.update(l,r,read());
        else
        {
            ll ans=0;
            for(register int j=l;j<=r;j++) ans+=check(j);
            printf("%d\n",ans);
        }
    }
}
inline void task2()
{
    in(m); treeB.clear(n);
    for(register int i=1;i<=n;i++) if(check(i)) treeB.update(i,i,1);
    for(register int i=1;i<=m;i++)
    {
        in(l); in(r);
        printf("%d\n",treeB.query(l,r));
    }
}
inline ll read()
{
    ll num=0,f=1;
    char ch=getchar();
    while((ch<'0' || ch>'9') && ch!='-') ch=getchar();
    if(ch=='-') {f=-1; ch=getchar();}
    while(ch>='0' && ch<='9')
    {
        num=(num<<3)+(num<<1)+ch-'0';
        ch=getchar();
    }
    return num*f;
}
posted @ 2019-02-20 17:40  常青藤的花语  阅读(158)  评论(0编辑  收藏  举报

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。