zoukankan      html  css  js  c++  java
  • bzoj 2821 分块处理

    大题思路就是分块,将n个数分成sqrt(n)个块,然后

    处理出一个w数组,w[i,j]代表第i个块到第j个块的答案

    那么对于每组询问l,r如果l,r在同一个块中,直接暴力做就行了

    如果不在同一个块中,l,r区间中整块的部分可以直接由w数组得到答案

    然后多出来的部分暴力处理下出现次数,然后再预处理一个b数组,代表没

    个数出现的位置,且每个数都连续,那么我们可以二分的找出在多余部分出现的

    每个数在整区间内出现多少次,然后和多余部分出现的累加,判断奇偶更新答案

    看了lyd的题解,写的挺好(其实这个题就是他出的。。),然后我写的

    pascal,他的C++的代码30s+A了,我就TLE了。。。

    话说今儿LYD生日,然后SHY发了个说说祝他生日快乐,是我想多了。。。

    /**************************************************************
        Problem: 2821
        User: BLADEVIL
        Language: Pascal
        Result: Time_Limit_Exceed
    ****************************************************************/
     //By BLADEVIL
    {$inline on}
    var
        n, t, m                     :longint;
        a, b, c                     :array[0..100010] of longint;
        st, ed, s, e, v, q          :array[0..100010] of longint;
        w                           :array[0..400,0..400] of longint;
     
    procedure swap(var a,b:longint);inline;
    var
        c                           :longint;
    begin
        c:=a; a:=b; b:=c;
    end;
         
    function calc(k,x,y:longint):longint;inline;
    var
        l, r, mid                   :longint;
    begin
        if x>y then exit(0);
        l:=st[k]; r:=ed[k];
        while l<r do
        begin
            mid:=(l+r+1)>>1;
            if b[mid]<x then l:=mid else r:=mid-1;
        end;
        if b[l]>=x then dec(l);
        x:=l;
        l:=st[k]; r:=ed[k];
        while l<r do
        begin
            mid:=(l+r+1)>>1;
            if b[mid]>y then r:=mid-1 else l:=mid;//
        end;
        if b[l]>y then dec(l);
        y:=l;
        exit(y-x);
    end;
         
    procedure main;inline;
    var
        i, j, k                     :longint;
        p, tot, l, r                :longint;
        now, cnt                    :longint;
        x, y                        :longint;
         
    begin  
        read(n,t,m);
        for i:=1 to n do read(a[i]);
        for i:=1 to n do inc(c[a[i]]);
        tot:=0;
        for i:=1 to t do
        begin
            st[i]:=tot+1;
            inc(tot,c[i]);
            ed[i]:=tot;
        end;
        fillchar(c,sizeof(c),0);
        for i:=1 to n do
        begin
            b[st[a[i]]+c[a[i]]]:=i;
            inc(c[a[i]]);
        end;
        p:=trunc(sqrt(n));
        l:=n div p;
        for i:=1 to p do
        begin
            s[i]:=(i-1)*l+1;
            e[i]:=i*l;
        end;
        if e[p]<n then
        begin
            inc(p);
            s[p]:=e[p-1]+1;
            e[p]:=n;
        end;
        for i:=1 to p do
        begin
            fillchar(c,sizeof(c),0);
            now:=0;
            for j:=i to p do
            begin
                for k:=s[j] to e[j] do
                begin
                    inc(c[a[k]]);
                    if (c[a[k]]>1) and (c[a[k]] and 1<>0) 
                        then dec(now) else
                    if (c[a[k]] and 1)=0 then inc(now);
                end;
                w[i,j]:=now;
            end;
        end;
        now:=0;
        for i:=1 to m do
        begin
            read(x,y);
            x:=(x+now) mod n+1;
            y:=(y+now) mod n+1;
            if x>y then swap(x,y);
            for j:=1 to p do
                if x<=e[j] then
                begin
                    l:=j;
                    break;
                end;
            for j:=p downto 0 do
                if y>=s[j] then
                begin
                    r:=j;
                    break;
                end;
            now:=w[l+1,r-1];
            if l=r then
            begin
                for j:=x to y do
                    if v[a[j]]<>i then
                    begin
                        v[a[j]]:=i;
                        c[a[j]]:=1;
                    end else
                    begin
                        inc(c[a[j]]);
                        if (c[a[j]] and 1)<>0 then
                            dec(now) else inc(now);
                    end;
            end else
            begin
                cnt:=0;
                for j:=x to e[l] do
                    if v[a[j]]<>i then
                    begin
                        v[a[j]]:=i;
                        c[a[j]]:=1;
                        inc(cnt);
                        q[cnt]:=a[j];
                    end else inc(c[a[j]]);
                for j:=s[r] to y do
                    if v[a[j]]<>i then
                    begin
                        v[a[j]]:=i;
                        c[a[j]]:=1;
                        inc(cnt);
                        q[cnt]:=a[j];
                    end else inc(c[a[j]]);
                for j:=1 to cnt  do
                begin
                    k:=calc(q[j],s[l+1],e[r-1]);
                    if k=0 then
                    begin
                        if c[q[j]] and 1=0 then inc(now)
                    end else
                    if (k and 1<>0) and (c[q[j]] and 1<>0) then inc(now) else
                    if (k and 1=0) and (c[q[j]] and 1<>0) then dec(now);
                end;
            end;
            writeln(now);
        end;
         
    end;
     
     
    begin
        main;
    end.
  • 相关阅读:
    3.2 线程复用:线程池
    3.1.7 线程阻塞工具类:LockSupport
    3.1.6 循环栅栏:CyclicBarrier
    3.1.4 读写锁
    3.1.5 倒计时器:CountDownLatch
    3.1.3 允许多个线程同时访问:信号量
    3.1.2 condition 条件
    3.1.1 重入锁 以及源码分析
    2.8.4 错误的加锁
    jsp中 scope="application" 表示
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3496158.html
Copyright © 2011-2022 走看看