トピック
今日のレビューフェンウィックツリーは、Qiaowanテンプレートはこの質問を書きました。私は長い時間が、我々は戻って転送することができないので、問題は、この問題、フェンウィックツリーが、それは、このビットの値を保持されていても、何の関係も持っていると思うしたいと思い直面している待っていました。。。。
瞑想の後、ライン注文暴力にオフラインで実行しようと、母親へのTは知りませんでした。。。
そして、問題の巧みな解決策、いくつかの研究を開きます。これは、オフラインの順序だけでなく、謎に加えて、それを発見しました。配列を持つツリーの前で各点の統計では、この質問の嘘の鍵貢献。意外なことに、これは、ツリーでこの質問直角アレイソリューションの考え方である必要があります。考えてみましょうの指向範囲の要素の寄与この角度は実際にはかなり一般的ですので、ブログの集計レコードを書き込みます。
具体的なアイデア:
指向範囲フェンウィックツリー表現を追加するの寄与、新しい要素の配列の要素数は、その前部に貢献します。端的に何かが、この要素の前に、位置がそれ以外の場合は1 0です。
最初の読み取りのすべてのセクションに対処する、一種の右端に合わせて、オフライン処理を行います。配列添字Rのメンテナンス要素続いて、新しいセグメント内のトラバース部要素にRがフェンウィックツリーメンテナンスを加えました。フェンウィックツリーを追加する場合は、寄付の削除の前の場所ではなく、ポイントの寄与があった場合、要素は、前に現れたかどうかを検討します。
結果として、このこと範囲性を保証内のエンドポイントの現在の範囲に最初の要素から、同じ要素のすべての寄与が発生右端からのものです。その後、ちょうどrおよび間隔のに寄与Lの電流範囲に、メンテナンス終了後。
CおよびC ++スタイルのACコードを混ぜます。
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 1000050;
int a[N];
int num[N];
int pos[N];
int ans[N];
int n,m;
struct node
{
int l;
int r;
int code;
}b[N];
int lowBit(int k)
{
return k & (-k);
}
int cmp(node a,node b)
{
return a.r < b.r;
}
void add(int k,int num)
{
while(k <= n)
{
a[k] += num;
k += lowBit(k);
}
}
int get(int k)
{
int sum = 0;
while(k)
{
sum += a[k];
k -= lowBit(k);
}
return sum;
}
int main()
{
scanf("%d",&n);
for(int i = 1;i <= n;i++)
{
scanf("%d",&num[i]);
}
scanf("%d",&m);
for(int i = 0;i < m;i++)
{
scanf("%d%d",&b[i].l,&b[i].r);
b[i].code = i;
}
sort(b,b + m,cmp);
int r = 0;
node v;
for(int i = 0;i < m;i++)
{
v = b[i];
while(r < v.r)
{
r++;
if(pos[num[r]])
{
add(pos[num[r]],-1);
}
pos[num[r]] = r;
add(pos[num[r]],1);
}
ans[v.code] = get(v.r) - get(v.l - 1);
}
for(int i = 0;i < m;i++)
{
printf("%d\n",ans[i]);
}
}
正しいが、人生のJavaコードを疑うT:
import java.util.Arrays;
import java.util.Scanner;
class s implements Comparable<s>
{
int l;
int r;
int code;
public s(int l, int r, int code)
{
this.l = l;
this.r = r;
this.code = code;
}
public int compareTo(s o)
{
return r - o.r;
}
}
class TreeArray {
private int[] array;
private int size;
public TreeArray(int n)
{
size = n;
array = new int[n + 1];
}
private int lowBit(int k)
{
return k & (-k);
}
public void add(int k,int num)
{
while(k <= size)
{
array[k] += num;
k += lowBit(k);
}
}
public int get(int k)
{
int sum = 0;
while(k > 0)
{
sum += array[k];
k -= lowBit(k);
}
return sum;
}
public int get(int l,int r)
{
return get(r) - get(l - 1);
}
}
public class Main {
static int[] num = new int[1000050];
static int[] ans = new int[1000050];
static int[] c = new int[1000050];
static s[] a;
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
for(int i = 1;i <= n;i++)
{
num[i] = scan.nextInt();
}
int m = scan.nextInt();
a = new s[m];
for(int i = 0;i < m;i++)
{
a[i] = new s(scan.nextInt(),scan.nextInt(),i);
}
Arrays.sort(a);
s v;
TreeArray ta = new TreeArray(n);
int r = 0;
for(int i = 0;i < m;i++)
{
v = a[i];
while(r < v.r)
{
r++;
if(c[num[r]] != 0)
{
ta.add(c[num[r]], -1);
}
ta.add(r, 1);
c[num[r]] = r;
}
ans[v.code] = ta.get(v.l,v.r);
}
for(int i = 0;i < m;i++)
{
System.out.println(ans[i]);
}
}
}