Mo Team Introduction questionnaire

Posted by sincspecv on Fri, 14 Jan 2022 13:07:23 +0100

Refer to blog portal ①
Refer to blog portal ②
Gate of question list
(pay attention to the clever use of metaphysical card constant technique, and then the pointer must be able to move O(1))

topic

SPOJ - DQUERY

Given a sequence of positive integers, ask m times, and the number of different intervals each time.
(Mo team board question)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
const int maxn = 1e6+10;
const int mx = 40;
const int mod = 1e9+7;
const ll inf = 34359738370;
const int INF = 1e9+7;
const double pi = acos(-1.0);
//Find the number of different numbers of [l,r] each time
int n,m,a[maxn];
int block;
int color[maxn];
int ans;
int ANS[maxn];
struct node 
{
    int l,r,id;
}q[maxn];
inline bool cmp(const node &a,const node &b) //odd-even sort 
{
    return (a.l/block)^(b.l/block)?a.l<b.l:(((a.l/block)&1)?a.r<b.r:a.r>b.r);
}
inline void del(int x) 
{
    color[a[x]]--;
    if(color[a[x]] == 0) ans--;
}
inline void add(int x) 
{
    color[a[x]]++;
    if(color[a[x]] == 1) ans++;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",a+i);
    scanf("%d",&m);
    for(int i=1;i<=m;i++) 
    {
        scanf("%d %d",&q[i].l,&q[i].r);
        q[i].id=i;
    }
    block=n/sqrt(m*2/3);
    sort(q+1,q+m+1,cmp);
    int l=q[1].l,r=q[1].l-1;
    for(int i=1;i<=m;i++) 
    {
        int ql=q[i].l,qr=q[i].r;
        while(l<ql) del(l++);
        while(r>qr) del(r--);
        while(l>ql) add(--l);
        while(r<qr) add(++r);
        ANS[q[i].id]=ans;
    }
    for(int i=1; i<=m ;i++) {printf("%d\n",ANS[i]); }
    return 0;
}

P2709 small B's inquiry

Question meaning: given a sequence of integers, ask the number in one interval at a time ∑ l r ( c [ i ] ) 2 \sum_{l}^{r} (c[i])^2 Σ lr (c[i])2,c[i] represents the number of times the number I appears in [l,r]
(Mo team board question, maintain the number of numbers in the interval and the contribution caused by the change of the square of the number)

  • add : n ² -> (n+1) ² , Add 2n+1 to the answer
  • del : n ² -> (n-1) ² , Add - 2n+1 to the answer
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define re register
const int maxn = 5e4+10;
const int mx = 40;
const int mod = 1e9+7;
const ll inf = 34359738370;
const int INF = 1e9+7;
const double pi = acos(-1.0);
//Find [l,r] in a given sequence Σ ci ²  Ci indicates the number of occurrences of i
int n,m,k;
int num[maxn];
int a[maxn];
ll ans=0;
ll ANS[maxn];
struct node 
{
    int l,r,id;
}q[maxn];
int block;
inline bool cmp(const node &a,const node &b) //odd-even sort 
{
    return (a.l/block)^(b.l/block)?a.l<b.l:(((a.l/block)&1)?a.r<b.r:a.r>b.r);
}
inline void del(int x) 
{
    ans += (-2*num[a[x]]+1) ;
    num[a[x]]--;
}
inline void add(int x)
{
    ans += (2*num[a[x]]+1) ;
    num[a[x]]++;
}

int main()
{
    scanf("%d %d %d",&n,&m,&k);
    block=n/sqrt(m*2/3);
    for(re int i=1;i<=n;i++) 
    {
        scanf("%d",a+i);
    }
    for(re int i=1;i<=m;i++)
    {
        scanf("%d %d",&q[i].l,&q[i].r);
        q[i].id=i;
    }
    sort(q+1,q+m+1,cmp);
    int l=q[1].l,r=q[1].l-1;
    for(re int i=1;i<=m;i++) 
    {
        int ql=q[i].l,qr=q[i].r;
        while(l < ql) del(l++);
        while(r > qr) del(r--);
        while(l > ql) add(--l);
        while(r < qr) add(++r);
        ANS[q[i].id]=ans;
    }
    for(int i=1;i<=m;i++) printf("%lld\n",ANS[i]);
    return 0;
}

P1494 [national training team] little Z's socks

Question meaning: given an integer sequence, m queries, and the probability of taking two identical numbers in the interval [l,r] each time. (expressed by the simplest fraction)

cnt[x] represents the number of times x appears in the interval, and len represents the length of the current interval, then the probability is:
∑ C 2 c n t [ x ] C 2 l e n \frac{\sum C_{2}^{cnt[x]} }{C_{2}^{len} } C2len​∑C2cnt[x]​​

Simplification: ∑ ( c n t [ x ] 2 − c n t [ x ] ) l e n ∗ ( l e n − 1 ) \frac{\sum (cnt[x]^2 -cnt[x]) }{len*(len-1)} len∗(len−1)∑(cnt[x]2−cnt[x])​
Further simplification: ∑ c n t [ x ] 2 − l e n l e n ∗ ( l e n − 1 ) \frac{\sum cnt[x]^2 -len }{len*(len-1)} len∗(len−1)∑cnt[x]2−len​

So every time the pointer moves, the information to be maintained is the contribution of a square number. The same maintenance method as the second question.

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define re register
#pragma GCC optimize(2)
const int maxn = 6e4+10;
const int mx = 40;
const int mod = 1e9+7;
const ll inf = 34359738370;
const int INF = 1e9+7;
const double pi = acos(-1.0);
//Given a sequence, find the probability (expressed by the simplest fraction) of two identical numbers when any two numbers are selected in [l,r]
//Let's assume that we have found the answer in a certain interval, and we can know it by hand pushing with the counting formula
//When the pointer moves left and right, only the square item of num[x] needs to be maintained 
//Add 1 square item to increase 2n+1 minus 1 square item to increase - 2n+1
int n,m,block;
int a[maxn];
int num[maxn];
ll tot=0;//
ll ANS[maxn][2];
struct node 
{
    int l,r,id;
}q[maxn];
inline bool cmp(const node &a,const node &b) //odd-even sort 
{
    return (a.l/block)^(b.l/block)?a.l<b.l:(((a.l/block)&1)?a.r<b.r:a.r>b.r);
}
inline void del(int x) 
{
    tot+=-2*num[a[x]]+1;
    num[a[x]]--;//This number is reduced by 1
}
inline void add(int x)
{
    tot+=2*num[a[x]]+1;
    num[a[x]]++;//Increase this number by one
}
int main()
{
    scanf("%d %d",&n,&m);
    block=n/sqrt(m*2/3);
    for(int i=1;i<=n;i++) scanf("%d",a+i);
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d",&q[i].l,&q[i].r);
        q[i].id=i;
    }
    sort(q+1,q+m+1,cmp);
    int l=q[1].l,r=q[1].l-1;
    for(int i=1;i<=m;i++) 
    {
        int ql=q[i].l,qr=q[i].r;
        while(l<ql) del(l++);
        while(r>qr) del(r--);
        while(l>ql) add(--l);
        while(r<qr) add(++r);
        int L=r-l+1;
        if(L == 1) //Special judgment
        {
            ANS[q[i].id][0] = 0;
            ANS[q[i].id][1] = 1;
            continue;
        }
        ANS[q[i].id][0] = tot-L;//molecule
        ANS[q[i].id][1] = 1ll*L*(L-1);//Denominator, pit: possible explosion int
        ll gd=__gcd(ANS[q[i].id][0],ANS[q[i].id][1]);
        ANS[q[i].id][0] /= gd;
        ANS[q[i].id][1] /= gd;
    }
    for(int i=1;i<=m;i++) 
    {
        printf("%lld/%lld\n",ANS[i][0],ANS[i][1]);
    }
    return 0;
}

CF617E XOR and Favorite Number

Question meaning: given the integer interval and natural number k, m queries, how many sub segments of each query interval [l,r] satisfy XOR, and the result is K.

The sub segments are continuous. We can think of using the prefix XOR array to simplify the sub segment XOR operation into the XOR of two elements of the prefix array. Namely:

a [ 4 ] ⊕ a [ 5 ] ⊕ a [ 6 ] = ( a [ 1 ] ⊕ a [ 2 ] . . . a [ 6 ] ) ⊕ ( a [ 1 ] ⊕ a [ 2 ] ⊕ a [ 3 ] ) a[4] \oplus a[5] \oplus a[6] = (a[1] \oplus a[2]...a[6]) \oplus (a[1] \oplus a[2]\oplus a[3]) a[4]⊕a[5]⊕a[6]=(a[1]⊕a[2]...a[6])⊕(a[1]⊕a[2]⊕a[3])

The problem is transformed into: each time we ask how many pairs (i,j) in the prefix XOR array satisfy pre[i]^pre[j]==k

cnt[i] indicates the number of occurrences of element I. when the pointer moves, you can O (1) maintain the answer

  • For pit points, k can be equal to 0. At this time, cnt[i]-1 should be deleted instead of cnt[i]
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair<int,int>
#define re register
const int maxn = 1e5+10;
const int mx = 40;
const int mod = 1e9+7;
const ll inf = 34359738370;
const int INF = 1e9+7;
const double pi = acos(-1.0);
//Given an integer sequence and given a constant k m times, how many sub segments in each question [l,r] satisfy XOR and the result is K
//The sub segment is associated with the preprocessed prefix XOR array pre a [i] ^ a [i + 1]^ a[j] == pre[i-1]^pre[j]
//The question is how many exclusive or results in [l-1,r] are k
int a[maxn],n,m,k,block;
struct node 
{
    int l,r,id;
}q[maxn];
ll num[20*maxn];//Be ca re ful to drive 2e6, or you'll be late
ll ans[maxn],ret=0;
inline bool cmp(const node &a,const node &b) //odd-even sort 
{
    return (a.l/block) ^ (b.l/block) ? a.l<b.l : (((a.l/block)&1) ? a.r < b.r:a.r>b.r) ;
}
inline void del(int x)
{
    ret-=num[a[x]^k];
    num[a[x]]--;
    if(!k) //k==0. At this time, a[x]^a[x]==k, num[a[x]]-1 should be deleted 
    {
        ret++;
    }
}
inline void add(int x)
{
    ret+=num[a[x]^k];
    num[a[x]]++;
}
int main()
{
    scanf("%d %d %d",&n,&m,&k);
    block=sqrt(n);
    for(int i=1;i<=n;i++)
    {
        int t;
        scanf("%d",&t);
        a[i]=a[i-1]^t;
    }
    for(int i=1;i<=m;i++) 
    {
        scanf("%d %d",&q[i].l,&q[i].r);
        q[i].l--;//The corresponding pre array interval is [l-1,r]
        q[i].id=i;
    }
    sort(q+1,q+m+1,cmp);
    int l=q[1].l,r=q[1].l-1;
    for(int i=1;i<=m;i++)
    {
        int ql=q[i].l,qr=q[i].r;
        while(l < ql) del(l++);
        while(l > ql) add(--l);
        while(r < qr) add(++r);
        while(r > qr) del(r--);
        ans[q[i].id]=ret;
    }
    for(int i=1;i<=m;i++) printf("%lld\n",ans[i]);
    return 0;
}

P3709 uncle's string question

Main idea: given a sequence of positive integers, m queries, and the number of modes in each query interval.

  • We use num[i] to represent the number of occurrences of the number I, cnt[i] to represent the number of occurrences of the number I, and ans to maintain the number of occurrences of the mode in the current interval
  • When the pointer moves, maintain num [], CNT [], and ans respectively
#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
#define ll long long
#define pii pair<int,int>
#define re register
const int maxn = 2e5+10;
const int mx = 40;
const int mod = 1e9+7;
const ll inf = 34359738370;
const int INF = 1e9+7;
const double pi = acos(-1.0);
//Given a sequence of integers, given a constant k m times, the number of occurrences of each interval mode
//num[i] indicates the number of occurrences of element I, cnt[i] indicates the total number of occurrences of I, and ans records the number of occurrences of mode in the current interval
//Add: CNT [num [i]] --, CNT [+ + num [i]] + + update ans=max(ans,num[i]) 
//Del: CNT [num [i]] --, CNT [-- [num [i]] + + if a[i] before deletion is the mode and the only mode, then ans--
int n0,m,block;
int a[maxn],b[maxn],n;//Discretization
int num[maxn],cnt[maxn];//How many times do i occur
int ans=0,ANS[maxn];//Number of occurrences of mode
struct node 
{
    int l,r,id;
}q[maxn];
inline bool cmp(const node &a,const node &b) //odd-even sort 
{
    return (a.l/block) ^ (b.l/block) ? a.l<b.l : (((a.l/block)&1) ? a.r < b.r:a.r>b.r) ;
}
inline void del(int x) 
{
    cnt[num[a[x]]]--;
    if(num[a[x]]==ans && !cnt[num[a[x]]]) ans--;//There is only one mode a[x], and the number of occurrences is reduced by 1
    cnt[--num[a[x]]]++;
}
inline void add(int x)
{
    cnt[num[a[x]]]--;
    cnt[++num[a[x]]]++;
    ans=max(ans,num[a[x]]);
}
int main()
{
    scanf("%d %d",&n0,&m);
    block=sqrt(n0);
    for(re int i=1;i<=n0;i++) 
    {
        scanf("%d",a+i);
        b[i]=a[i];
    }
    sort(b+1,b+n0+1);
    n=unique(b+1,b+n0+1)-b-1;
    for(int i=1;i<=n0;i++) 
    {
        a[i]=lower_bound(b+1,b+n+1,a[i])-b;
    }
    for(int i=1;i<=m;i++) 
    {
        scanf("%d %d",&q[i].l,&q[i].r);
        q[i].id=i;
    }
    sort(q+1,q+m+1,cmp);
    int l=q[1].l,r=q[1].l-1;
    for(int i=1;i<=m;i++) 
    {
        int ql=q[i].l,qr=q[i].r;
        while(l < ql) del(l++);
        while(r > qr) del(r--);
        while(l > ql) add(--l);
        while(r < qr) add(++r);
        ANS[q[i].id]=ans;
    }
    for(int i=1;i<=m;i++) printf("%d\n",-ANS[i]);
    return 0;
}