2019雅礼集训 D5T2 sequence [乱搞]

题目描述:

样例:

input1:
3 2 1
1 2 3
2 2
1 3

output1:
1
6

input2:
3 2 2
1 2 3
2 2
1 3

output2:
1
4

input3:
3 2 3
1 2 3
2 2
1 3

output3:
0
3

数据范围与约定:

标签:乱搞


出题人说这是签到题,那我没做出来是不是该退役了?

注意到左端点不变时区间的按位与值最多会变化\(log\)次。

从右往左枚举左端点,记录一个nxt数组表示下一次出现变化的位置在哪里。

出现变化时判一下是否整除,若整除则区间方案数+1

将询问离线,左端点扫到询问的左端点时求一个区间和即可。

奇奇怪怪的复杂度,好像是\(O(n \log n \log a_i +q \log n)\)

毒瘤出题人卡常数……

代码:

#include<bits/stdc++.h>
namespace my_std{
    using namespace std;
    #define rep(i,x,y) for (register int i=(x);i<=(y);++i)
    #define drep(i,x,y) for (register int i=(x);i>=(y);--i)
    #define sz 100010
    typedef long long ll;
    template<typename T>
    inline void read(T& t)
    {
        t=0;char f=0,ch=getchar();
        double d=0.1;
        while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
        while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
        if(ch=='.')
        {
            ch=getchar();
            while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();
        }
        t=(f?-t:t);
    }
    template<typename T,typename... Args>
    inline void read(T& t,Args&... args){read(t); read(args...);}
    void file()
    {
        #ifndef ONLINE_JUDGE
        freopen("a.txt","r",stdin);
        #endif
    }
}
using namespace my_std;

int n,Q,K;
struct hh{int pos,r,id;}q[sz*5];
inline bool cmp(const hh &x,const hh &y){return x.pos>y.pos;}
int a[sz];
ll ans[sz*5];

#define LB(x) ((x)&(-(x)))
ll sum1[sz],sum2[sz];
inline void add(int x,ll y){for (register int i=x;i<=n;i+=LB(i)) sum1[i]+=y,sum2[i]+=y*x;}
inline ll query(int x){ll ret=0;for (register int i=x;i;i^=LB(i)) ret+=1ll*(x+1)*sum1[i]-sum2[i];return ret;}
inline void add(int l,int r,int w){add(l,w);add(r+1,-w);}
inline ll query(int l,int r){return query(r)-query(l-1);}

int nxt[sz];

int main()
{
    file();
    int x,y;
    read(n,Q,K);
    rep(i,1,n) read(a[i]);
    rep(i,1,Q) read(x,y),q[i]=(hh){x,y,i};
    sort(q+1,q+Q+1,cmp);
    int k=1;
    drep(i,n,1)
    {
        nxt[i]=i+1;
        int cur=a[i],lst=i;
        for (int j=i+1,pre=i;j<=n;j=nxt[pre=j])
        {
            if ((cur&a[j])^cur)
            {
                if (cur%K==0) add(lst,j-1,1);
                cur&=a[j];lst=j;
            }
            else nxt[pre]=nxt[j];
        }
        if (cur%K==0) add(lst,n,1);
        while (q[k].pos==i&&k<=Q) ans[q[k].id]=query(1,q[k].r),++k;
    }
    rep(i,1,Q) printf("%lld\n",ans[i]);
}

猜你喜欢

转载自www.cnblogs.com/p-b-p-b/p/10252477.html