SPOJ DQUERY:TLE即使有几分?有几分、SPOJ、DQUERY、TLE

2023-09-11 23:12:10 作者:了了风月

下面是我要解决,我使用的事实,问题是preFIX总和[I] - preFIX总和[I-1] 导致频率为大于零,以确定鲜明的数字,然后我消除了频率,但即使有位,我得到一个TLE

鉴于正数A1的序列,A2,...,an和一数目的d查询。

一个D-查询是一对(I,J)(1≤I≤Ĵ≤N)。

Devin和Cameron Thistle分别玩一把Jimi Hendrix Fender Strat 和Jazz Bass

有关各d查询(I,J),则必须返回在子序列艾不同元件的数量,AI + 1,...,AJ。

 输入

线路1:N(1≤N≤30000)。
线路2:N号A1,A2,...,一(1≤艾≤106)。
线3:Q(1≤q≤200000)中,d-查询的数量。
在下一q行,每行包含2号I,J
再presenting一个D-查询(1≤I≤Ĵ≤N)。

输出

对于每一个的d查询(I,J),打印时,在不同的元素数
子AI,AI + 1,...,AJ在一行。
例

输入
五
1 1 2 1 3
3
1 5
2 4
3 5

输出
3
2
3
 

在code是:

 的#include<的iostream>
#包括<算法>
#包括<载体>
#包括< stdlib.h中>
#包括< stdio.h中>
长期的typedef长整型LL;
使用名字空间std;
无效更新(LL N,LL VAL,矢量< LL>和b);
LL阅读(LL N,矢量< LL>和b);
LL readsingle(LL N,矢量< LL>和b);
空隙地图(矢量< LL>&安培;一,矢量< LL>和b,LL n)的/ ****相对映射*** /
{
    LL温度;
    a.clear();
    b.clear();
    对于(LL我= 0;我n种;我++)
    {
        CIN>>温度;
        a.push_back(临时);
        b.push_back(临时);
    }
    排序(b.begin(),b.end());
    对于(LL我= 0;我n种;我++)
        *(a.begin()+ I)=(LOWER_BOUND(b.begin(),b.end(),A [1]) -  b.begin())+ 1;
    b.assign(N + 1,0);
}
诠释的main()
{
    LL N;
    霉素>将N;
    矢量< LL>的a,b;
    图(A,B,n)的;
    LL吨;
    CIN>>吨;
    而(T--)
    {
        LL L,U;
        b.assign(N + 1,0);
        CIN>> L>> U;
        L  - ; / ***减少从零开始的索引**** /
        u--;
        对于(LL其中i = 1; I< = U;我++)
            更新(A [1],1,b)条;
        LL CONT = 0;
        对于(LL其中i = 1; I< = U;我++)
            如果(readsingle(A [1],B)大于0)
        {
            续++;
            更新(A [1], -  readsingle(A [1],b)中,二); / ***消除频率* /
        }
        COUT<<续<< ENDL;
    }
    返回0;
}
LL readsingle(LL N,矢量< LL>和b)
{
    返回读取(N,B)-read第(n-1,B);
}
LL阅读(LL N,矢量< LL>和b)
{
    LL总和= 0;
    为(N;总和+ = B [N],正= N&安培; -n);
    返回总和;
}
无效更新(LL N,LL VAL,矢量< LL>和b)
{
    对于(; N< = b.size(); B [N] + = VAL,N + = N&安培; -n);
}
 

解决方案

您使用的算法是太慢了。对于每个查询,您遍历整个查询范围,这已经给ñ* Q 操作(很明显,这是太多)。这里是一个更好的解决方案(它有 O((N + Q)* log n)的时间和 O(N + Q)空间复杂度(这是一个离线解决方案):

让我们通过他们的右端的所有查询排序(没有必要明确地对它们进行排序,你可以查询只需添加到一个合适的位置(距离 0 N - 1 ))

现在让我们遍历所有位置的数组中从左至右,保持一点。在BIT每个位置可以是 1 (这意味着在位置一个新的元素)或者 0 (最初,它充满了零)。

对于每一个元素 A [1] :如果此元素的第一次出现,只需添加一个到在位的位置。否则, 1 添加到这个元素previous出现的位置,然后添加 1 位置。

这个问题的答案查询(左,右)只是总和的所有元素从离开右键

要保持每个元素的最后出现,你可以使用地图。

这是可能使用持久段树(时间复杂度是一样的,同样的复杂性将成为 0,使其在线(N *日志中n + q) ),但它并不需要在这里。

Here is The Problem i Want to Solve , I am Using The Fact That Prefix Sum[i] - Prefix Sum[i-1] Leads to Frequency being Greater than Zero to Identify Distinct Digits and Then i am Eliminating The Frequency , But Even with BIT , i am Getting a TLE

Given a sequence of n numbers a1, a2, ..., an and a number of d-queries.

A d-query is a pair (i, j) (1 ≤ i ≤ j ≤ n).

For each d-query (i, j), you have to return the number of distinct elements in the subsequence ai, ai+1, ..., aj.

Input

Line 1: n (1 ≤ n ≤ 30000).
Line 2: n numbers a1, a2, ..., an (1 ≤ ai ≤ 106).
Line 3: q (1 ≤ q ≤ 200000), the number of d-queries.
In the next q lines, each line contains 2 numbers i, j 
representing a d-query (1 ≤ i ≤ j ≤ n).

Output

For each d-query (i, j), print the number of distinct elements in the 
subsequence ai, ai+1, ..., aj in a single line.
Example

Input
5 
1 1 2 1 3
3
1 5
2 4
3 5

Output
3
2
3

the code is:

#include <iostream>
#include <algorithm>
#include <vector>
#include <stdlib.h>
#include <stdio.h>
typedef long long int ll;
using namespace std;
void update(ll n, ll val, vector<ll> &b);
ll read(ll n,vector<ll> &b);
ll readsingle(ll n,vector<ll> &b);
void map(vector<ll> &a,vector<ll> &b,ll n)  /**** RElative Mapping ***/
{
    ll temp;
    a.clear();
    b.clear();
    for(ll i=0; i<n; i++)
    {
        cin>>temp;
        a.push_back(temp);
        b.push_back(temp);
    }
    sort(b.begin(),b.end());
    for(ll i=0; i<n; i++)
        *(a.begin()+i) = (lower_bound(b.begin(),b.end(),a[i])-b.begin())+1;
    b.assign(n+1,0);
}
int main()
{
    ll n;
    cin>>n;
    vector<ll> a,b;
    map(a,b,n);
    ll t;
    cin>>t;
    while(t--)
    {
        ll l ,u;
        b.assign(n+1,0);
        cin>>l>>u;
        l--;/*** Reduce For Zero Based INdex ****/
        u--;
        for(ll i=l;i<=u;i++)
            update(a[i],1,b);
        ll cont=0;
        for(ll i=l;i<=u;i++)
            if(readsingle(a[i],b)>0)
        {
            cont++;
            update(a[i],-readsingle(a[i],b),b); /***Eliminate The Frequency */
        }
        cout<<cont<<endl;
    }
    return 0;
}
ll readsingle(ll n,vector<ll> &b)
{
    return read(n,b)-read(n-1,b);
}
ll read(ll n,vector<ll> &b)
{
    ll sum=0;
    for(; n; sum+=b[n],n-=n&-n);
    return sum;
}
void update(ll n, ll val, vector<ll> &b)
{
    for(; n<=b.size(); b[n]+=val,n+=n&-n);
}

解决方案

The algorithm you use is too slow. For each query, your iterate over the entire query range, which already gives n * q operations(obviously, it is way too much). Here is a better solution(it has O((n + q) * log n) time and O(n + q) space complexity (it is an offline solution):

Let's sort all queries by their right end(there is no need to sort them explicitly, you can just add a query to an appropriate position (from 0 to n - 1)).

Now let's iterate over all positions in the array from left to right and maintain a BIT. Each position in the BIT is either 1(it means that there is a new element at position i) or 0(initially, it is filled with zeros).

For each element a[i]: if it the first occurrence of this element, just add one to the i position in the BIT. Otherwise, add -1 to the position of the previous occurrence of this element and then add 1 to the i position.

The answer to the query (left, right) is just sum for all elements from left to right.

To maintain the last occurrence of each element, you can use a map.

It is possible to make it online using persistent segment tree(the time complexity would be the same, the same complexity would become O(n * log n + q)), but it is not required here.