zoukankan      html  css  js  c++  java
  • bzoj 1878 SDOI2009树状数组 离线操作

    本来想写2120的,结果想起来了这个

    我们先对于询问左端点排序,用树状数组存区间字母个数,对于每种字母,

    第一次出现的位置记录为1,剩下的记录为0,然后记录下,每种颜色

    后面第一个和他相同颜色的位置

    然后扫询问,对于一个询问直接输出区间和,然后假设当前询问是

    l1,r1,下一询问是,l2,r2,我们把l1到l2区间内的每个位置颜色的后一颜色

    赋值成1,然后继续处理下个询问就好了。

    /**************************************************************
        Problem: 1878
        User: BLADEVIL
        Language: Pascal
        Result: Accepted
        Time:3260 ms
        Memory:29524 kb
    ****************************************************************/
     
    //By BLADEVIL
    var
        n, m                :longint;
        a                   :array[0..50010] of longint;
        l, r                :array[0..200010] of longint;
        other               :array[0..50010] of longint;
        last, first         :array[0..1000010] of longint;
        num, ans            :array[0..1000010] of longint;
        c                   :array[0..3000010] of longint;
        tot                 :longint;
         
    procedure swap(var a,b:longint);
    var
        c                   :longint;
    begin
        c:=a; a:=b; b:=c;
    end;
         
    procedure qs(low,high:longint);
    var
        i, j, x             :longint;
    begin
        i:=low; j:=high; x:=l[(i+j) div 2];
        while i<j do
        begin
            while l[i]<x do inc(i);
            while l[j]>x do dec(j);
            if i<=j then
            begin
                swap(l[i],l[j]); swap(r[i],r[j]);
                swap(num[i],num[j]);
                inc(i); dec(j);
            end;
        end;
        if i<high then qs(i,high);
        if j>low then qs(low,j);
    end;
     
    procedure qs1(low,high:longint);
    var
        i, j, x             :longint;
    begin
        i:=low; j:=high; x:=num[(i+j) div 2];
        while i<j do
        begin
            while num[i]<x do inc(i);
            while num[j]>x do dec(j);
            if i<=j then
            begin
                swap(l[i],l[j]); swap(r[i],r[j]);
                swap(num[i],num[j]); swap(ans[i],ans[j]);
                inc(i); dec(j);
            end;
        end;
        if i<high then qs1(i,high);
        if j>low then qs1(low,j);
    end;
     
     
    procedure init;
    var
        i                   :longint;
    begin
        read(n);
        for i:=1 to n do
        begin
            read(a[i]);
            if tot<a[i] then tot:=a[i];
        end;
         
        read(m);
        for i:=1 to m do read(l[i],r[i]);
        for i:=1 to m do num[i]:=i;
        qs(1,m);
        for i:=1 to n do
            if last[a[i]]<>0 then
            begin
                other[last[a[i]]]:=i;
                last[a[i]]:=i;
            end else
            begin
                last[a[i]]:=i;
                first[a[i]]:=i;
            end;
    end;
     
    procedure add(x:longint);
    begin
        while x<=n do
        begin
            c[x]:=c[x]+1;
            x:=x+(x and (-x));
        end;
    end;
     
    function ask(x:longint):longint;
    begin
        ask:=0;
        while x>0 do
        begin
            ask:=ask+c[x];
            x:=x-(x and (-x));
        end;
    end;
     
    procedure main;
    var
        i, j                :longint;
        ll                  :longint;
    begin
        for i:=1 to tot do if first[i]<>0 then add(first[i]);
        ll:=1;
        for i:=1 to m do
        begin
            for j:=ll to l[i]-1 do if other[j]<>0 then add(other[j]);
            ans[i]:=ask(r[i])-ask(l[i]-1);
            ll:=l[i];
        end;
        qs1(1,m);
        for i:=1 to m do writeln(ans[i]);
    end;
     
    begin
        init;
        main;
    end.
  • 相关阅读:
    显示游标的属性
    显示游标的处理
    5:查询两表中的所有字段,满足性别为‘男’的记录(使用语句块)
    JS 进阶1
    JS 小练习
    驼峰法
    JS 入门四
    JS 入门三
    javascript中window.open()与window.location.href的区别(转)
    JavaScript 之日起对象(转)
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3464258.html
Copyright © 2011-2022 走看看