1. 程式人生 > >HDU 6315 Naive Operations

HDU 6315 Naive Operations

排列 dig nod set sta file pro reg clu

http://acm.hdu.edu.cn/showproblem.php?pid=6315

題目

In a galaxy far, far away, there are two integer sequence $a$ and $b$ of length $n$.

$b$ is a static permutation of $1$ to $n$. Initially a is filled with zeroes.

There are two kind of operations:

1. add l r: add one for $a_l,a_{l+1}\dots a_r$

2. query l r: query $\sum_{i=l}^r\lfloor ai/bi \rfloor$

Input

There are multiple test cases, please read till the end of input file.

For each test case, in the first line, two integers n,q, representing the length of a,b and the number of queries.

In the second line, n integers separated by spaces, representing permutation b.

In the following q lines, each line is either in the form ‘add l r‘ or ‘query l r‘, representing an operation.

$1 \leqslant n,q \leqslant 100000, 1 \leqslant l \leqslant r\leqslant n$, there‘re no more than 5 test cases.

Output

Output the answer for each ‘query‘, each one line.

題解

其實根本不會做……

$\lfloor a/b \rfloor = \frac{a-a\%b}{b}$,記錄$a$和$a\%b$比較麻煩,因此記錄$\frac{a-a\%b}{b}=\boldsymbol{v}$和$a\%b=\boldsymbol{b}$(我就喜歡亂用符號= =)

那麽只需某處$\boldsymbol{b}=0$就將v單點修改+1,容易用線段樹寫出來……(註意可能同時有多個地方=0)

因為$n,q \leqslant 100000$,b又是一個1~n的排列,所以所有和小於$\sum_{i=1}^n\frac{n}{i}=n(\ln{n}+\gamma+\frac{1}{2n})\approx n\ln{n}<10^8$,所以可以用int存

但是為了確定某處的$\boldsymbol{b}$,直接暴力$q\times2n>10^9$肯定超時,因此需要技巧……

因為並不是所有的$\boldsymbol{b}$每時每刻都為0,所以還需要點技巧,將$\boldsymbol{b}$設為$b-a\%b$,所以只需要關心最小的那個$\boldsymbol{b}$,同樣可以用線段樹維護(+區間),每次維護$\log{n}$

加起來$\mathcal{O}(n\log{n})$

查詢的時候並不需要向下和向上更新

還要註意更新延遲變量$\text{d}\boldsymbol{b}$時不要寫成等號= =

技術分享圖片

AC代碼

#include<cstdio>
#include<cstdlib>
#include<cctype>
#include<cstring>
#include<algorithm>
#include<set>
#define REP(r,x,y) for(register int r=(x); r<(y); r++)
#define REPE(r,x,y) for(register int r=(x); r<=(y); r++)
#define PERE(r,x,y) for(register int r=(x); r>=(y); r--)
#ifdef sahdsg
#define DBG(...) printf(__VA_ARGS__),fflush(stdout)
#else
#define DBG(...) (void)0
#endif
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

char ch; int si;
char buf[1<<21],*p1=buf,*p2=buf;
int beof = 0;
#define gc() (beof?EOF:(p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(beof=EOF):*p1++))

template<class T>
inline void read(T &x) {
    x=0; si=1; for(ch=gc();!isdigit(ch) && ch!=‘-‘;ch=gc()) if(beof) return;
    if(ch==‘-‘){si=-1,ch=gc();} for(;isdigit(ch);ch=gc())x=x*10+ch-‘0‘;
    x*=si;
}
//template<class T, class...A> inline void read(T &x, A&...a){read(x); read(a...);}

#define MAXN 100007
int b[MAXN];

struct node {
    int v,b,db;
    int l,r;
} st[MAXN*4];

inline void st0(int p, int l, int r) {
    st[p].l=l, st[p].r=r, st[p].v=st[p].db=0;
    if(l==r) {
        st[p].b=b[l];
        return;
    }
    int m=(l+r)>>1;
    st0(p*2,l,m);
    st0(p*2+1,m+1,r);
    st[p].b=min(st[p*2].b,st[p*2+1].b);
}

inline void spreadb(int p) {
    if(st[p].db) {
        st[p*2].db+=st[p].db; st[p*2].b-=st[p].db;
        st[p*2+1].db+=st[p].db; st[p*2+1].b-=st[p].db;
        st[p].db=0;
    }
}

inline void op_C(int p) {
    if(st[p].l==st[p].r) {
        st[p].v++; st[p].b=b[st[p].l];
        return;
    }
    spreadb(p);
    if(!st[p*2].b) op_C(p*2);
    if(!st[p*2+1].b) op_C(p*2+1);
    st[p].v=st[p*2].v+st[p*2+1].v;
    st[p].b=min(st[p*2].b, st[p*2+1].b);
}

inline void opA(int p, int l, int r) {
    if(l<=st[p].l && r>=st[p].r) {
        st[p].b--; st[p].db++;
        if(st[p].b==0) {
            op_C(p);
        }
        return;
    }
    spreadb(p);
    int m=(st[p].l+st[p].r)>>1;
    if(l<=m) opA(p*2,l,r);
    if(r>m) opA(p*2+1,l,r);
    st[p].v=st[p*2].v+st[p*2+1].v;
    st[p].b=min(st[p*2].b, st[p*2+1].b);
}

inline int opQ(int p, int l, int r) {
    if(l<=st[p].l && r>=st[p].r) {
        return st[p].v;
    }
    int m=(st[p].l+st[p].r)>>1;
    int ans=0;
    if(l<=m) ans+=opQ(p*2,l,r);
    if(r>m) ans+=opQ(p*2+1,l,r);
    return ans;
}

int main() {
#ifdef sahdsg
    freopen("in.txt","r",stdin);
#endif
    int n,q;
    read(n);read(q);
    while(!beof) {
        REPE(i,1,n) read(b[i]);
        st0(1,1,n);
        while(0<q--) {
            char k; do k=gc(); while(isspace(k));
            int l,r; read(l); read(r);
            if(k==‘a‘) opA(1,l,r);
            else printf("%d\n", opQ(1,l,r));
        }
        read(n); read(q);

    }
    return 0;
}

HDU 6315 Naive Operations