CodeForces 1000F One Occurrence (线段树+离线/主席树)*

博客围绕一个序列查询问题展开,题目要求在给定序列和若干查询中,找出区间里只出现一次的数字。分析采用贪心思想,通过判断区间pre最小值与左端点的关系确定答案。介绍了线段树离线和主席树两种解法,时间复杂度为O(n+qlogn)。

题目链接:http://codeforces.com/problemset/problem/1000/F

题目大意

给定一个序列和若干个查询,
每次查询区间中只出现一次的那个数字,
若答案有若干个则输出任意一个,
否则输出零。

题目分析 

根据贪心的思想,对于一个特定的区间,
假设每个位置都有一个pre,即上一次出现该位置数的位置,
如果第一次出现明显位置应该为0,
一个区间中是否存在答案,就是看这个区间的pre最小值,是否
大于左端点,那么我们只要看其区间最小值即可,注意要存个二元组,,因为
如果pre值为0则无法确定位置数,一种常规方法是线段树离线,
因为在线的话不确定查询区间出现的时间顺序,
那么当前维护的线段树不会对以前的区间产生贡献,
离线可以解决这个问题,按右端点排序,直接往线段树按序更新值即可,
那么既然涉及到时间顺序的影响问题,主席树也是一个手段。
主席树就是暴力空间般把时间序都存储下来了,
但是一个时间刻只影响一条链所有空间不会特别大,
既然我们对每个扫描时间(总共n)都开线段树存储时间刻了,
那么对于这个时间线段树,当前位置的pre影响应该消去,
所以空间要开四倍左右,然后更新i位置用位置上的pre值即可。
最后直接在第r个树上区间查询找最小的即可。
时间复杂度:O(n+qlogn).

#include<bits/stdc++.h>
using namespace std;

#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long

#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=5e5+5;
const int maxm=2e7+5;
const int ub=1e6;
const int INF=1e9;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
/*
题目大意:
给定一个序列和若干个查询,
每次查询区间中只出现一次的那个数字,
若答案有若干个则输出任意一个,
否则输出零。

题目分析:
根据贪心的思想,对于一个特定的区间,
假设每个位置都有一个pre,即上一次出现该位置数的位置,
如果第一次出现明显位置应该为0,
一个区间中是否存在答案,就是看这个区间的pre最小值,是否
大于左端点,那么我们只要看其区间最小值即可,注意要存个二元组,,因为
如果pre值为0则无法确定位置数,一种常规方法是线段树离线,
因为在线的话不确定查询区间出现的时间顺序,
那么当前维护的线段树不会对以前的区间产生贡献,
离线可以解决这个问题,按右端点排序,直接往线段树按序更新值即可,
那么既然涉及到时间顺序的影响问题,主席树也是一个手段。
主席树就是暴力空间般把时间序都存储下来了,
但是一个时间刻只影响一条链所有空间不会特别大,
既然我们对每个扫描时间(总共n)都开线段树存储时间刻了,
那么对于这个时间线段树,当前位置的pre影响应该消去,
所以空间要开四倍左右,然后更新i位置用位置上的pre值即可。
最后直接在第r个树上区间查询找最小的即可。
时间复杂度:O(n+qlogn).
*/
int rt[maxn],ls[maxm],rs[maxm];
struct node{ int pos , val; };
node sum[maxm];
int tot=0;
void build(int& o,int l,int r){
    o=++tot;
    sum[o].val=INF;
    if(l==r) return;
    int mid=l+r>>1;
    build(ls[o],l,mid);
    build(rs[o],mid+1,r);
}
void update(int& o,int l,int r,int last,int p,int v){
    o=++tot;
    ls[o]=ls[last],rs[o]=rs[last];
    if(l==r){
        sum[o].val=v;
        sum[o].pos=l;
        return;
    }
    int mid=l+r>>1;
    if(p<=mid) update(ls[o],l,mid,ls[o],p,v);
    else update(rs[o],mid+1,r,rs[o],p,v);
    if(sum[ls[o]].val<sum[rs[o]].val) sum[o]=sum[ls[o]];
    else sum[o]=sum[rs[o]];
}
node query(int o,int l,int r,int pl,int pr){
    if(pl<=l&&r<=pr) return sum[o];
    if(sum[o].val==INF) return sum[o];
    int mid=l+r>>1;
    node tp1,tp2;
    tp2.val=INF;
    if(pl<=mid){
        tp1=query(ls[o],l,mid,pl,pr);
        if(tp1.val<tp2.val) tp2=tp1;
    }
    if(mid<pr){
        tp1=query(rs[o],mid+1,r,pl,pr);
        if(tp1.val<tp2.val) tp2=tp1;
    }
    return tp2;
}
int a[maxn],n,x,y,q;
int pre[maxn],last[maxn];
int main(){
    scanf("%d",&n);
    build(rt[0],1,n);
    rep(i,1,n+1) scanf("%d",&a[i]);
    rep(i,1,n+1){
        if(last[a[i]]) pre[i]=last[a[i]];
        last[a[i]]=i;
    }
    rep(i,1,n+1){
        if(pre[i]){
            int tmp;
            update(tmp,1,n,rt[i-1],pre[i],INF);
            update(rt[i],1,n,tmp,i,pre[i]);
        }
        else update(rt[i],1,n,rt[i-1],i,0);
    }
    scanf("%d",&q);
    rep(i,0,q){
        scanf("%d%d",&x,&y);
        node ret=query(rt[y],1,n,x,y);
        if(ret.val>=x) puts("0");
        else printf("%d\n",a[ret.pos]);
    }

    return 0;
}

 

#include <stdio.h> #include <string.h> #include <stdbool.h> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <limits.h> #define eps 1e-9 //unsigned int F[14000010]; //unsigned long long arr[7500005]; //double arr1[1000000]; //double arr2[1000000]; //double Arr[1000000]; //int arr[1000010] = { 0 }; //int arrn[10010] = { 0 }; //int arr[100][100]; //E3H! //int is_ry(int y) //{ // int result; // result = (y % 4 == 0 && y % 100 != 0) || (y % 400 == 0); // return result; //} //int D(int y, int m) //{ // int D[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 }; // int ds = D[m]; // if (m == 2 && is_ry(y)) // { // D[2] = 29; // return 29; // } // return ds; //} //E3M int Max(int a, int b) { int result; if (a >= b) { result = a; } else { result = b; } return result; } int Min(int a, int b) { int result; if (a <= b) { result = a; } else { result = b; } return result; } int main() { //C3A //long long T; //scanf("%lld", &T); //unsigned int a, b; //for (int i = 0; i < T; i++) //{ // scanf("%u %u", &a, &b); // unsigned int n1 = ~a; // unsigned int n2 = a & b; // unsigned int n3 = a | b; // unsigned int n4 = a ^ b; // unsigned int n5 = a << b; // unsigned int n6 = a >> b; // printf("%u %u %u %u %u %u\n", n1, n2, n3, n4, n5, n6); //} //return 0; //C3B //long long n; //scanf_s("%lld", &n); //printf("0 "); //for (int k = 1; k <= n; k++) //{ // int sum = 0; // int arr[101]; // int f = floor(log2(k)); // int K = k; // for (int i = 0; i <= f; i++) // { // int N = K & 1; // arr[i] = N; // K = K >> 1; // } // for (int j = 0; j <= f; j++) // { // if (arr[j] == 1) // { // sum++; // } // } // printf("%d ", sum); //} //return 0; //C3C //int nn; //scanf_s("%d", &nn); //int n; //for (int i = 0; i < nn; i++) //{ // int arr[101] = {0}; // unsigned long long n; // scanf_s("%llu", &n); // unsigned long long f = floor(log2(n)); // unsigned long long N = n; // for (int i = 0; i <= f; i++) // { // unsigned long long N = n & 1; // arr[i] = N; // n = n >> 1; // } // for (int j = 63; j >= 0; j=j-4) // { // printf("%d%d%d%d ", arr[j],arr[j-1],arr[j-2],arr[j-3]); // } // printf("\n"); //} //return 0; //C3D //int n; //unsigned int sum=0; //scanf_s("%d", &n); //for (int i = 0; i < n; i++) //{ // sum = 0; // int arr[101] = {0}; // unsigned int n; // scanf_s("%u", &n); // int f = floor(log2(n)); // unsigned int N = n; // for (int i = 0; i <= f; i++) // { // unsigned int N = n & 1; // arr[i] = N; // n = n >> 1; // } // for (int j = 0; j <= 32; j++) // { // sum = sum + pow(2, j) * arr[31-j]; // } // printf("%u\n", sum); //} //C3E //int nn; //scanf_s("%d", &nn); //for (int i = 0; i < nn; i++) //{ // int arr[101]; // int n; // scanf_s("%d", &n); // int f = floor(log2(n)); // int N = n; // for (int i = 0; i <= f; i++) // { // int N = n & 1; // arr[i] = N; // n = n >> 1; // } // int k = 0; // int Arr[101]; // for (int j = f; j >= 0; j--) // { // if (arr[j] == 1) // { // Arr[k] = j; // k++; // } // } // for (int t = 0; t < k; t++) // { // printf("%.0lf ", pow(2, Arr[t])); // } // printf("\n"); //} //return 0; //C3F //int n, q; //scanf_s("%d%u%d", &n, &F[0], &q); //int k; //for (int i = 1; i <= n; i++) //{ // unsigned int x = F[i - 1]; // x ^= x << 13; // x ^= x >> 17; // x ^= x << 5; // F[i] = x; //} //while (q--) //{ // scanf_s("%d", &k); // printf("%u\n", F[k]); //} //return 0; //C3G //int n; //int a; //int b=0; //scanf_s("%d", &n); //for (int i = 0; i < n; i++) //{ // scanf_s("%d", &a); // b = b ^ a; //} //printf("%d\n", b); //return 0; //E3A //int a, b, c, x; //scanf_s("%d%d%d%d", &a, &b, &c, &x); //int A = a * x * x + b * x + c; //printf("%d", A); //return 0; //E3B //int n; //scanf_s("%d", &n); //int i = n; //for (int i = n; i > 1; i--) //{ // printf("%d bottles of beer on the wall,\n", i); // printf("%d bottles of beer.\n", i); // printf("Take one down and pass it around,\n"); // if (i == 2) // { // printf("now there's %d more bottle of beer on the wall!\n", i-1); // } // else // printf("now there's %d more bottles of beer on the wall!\n", i - 1); //} // printf("1 bottle of beer on the wall,\n"); // printf("1 bottle of beer.\n"); // printf("Take one down and pass it around,\n"); // printf("there's no more bottles of beer on the wall!\n"); //return 0; //E3C //unsigned long long a, b; //while (scanf_s("%llu%llu", &a, &b) != EOF) //{ // unsigned long long i = 0; // unsigned long long t = 0; // for (i = 0; i < 64; i++) // { // unsigned long long ai = a >> i; // unsigned long long bi = b >> i; // unsigned long long Ai = ai & 1; // unsigned long long Bi = bi & 1; // if (Ai - Bi == 1) // { // t = t | (1ULL << i); // } // } // printf("%llu\n", t); //} //return 0; //E3D //int T, n; //scanf_s("%d", &T); //arr[1] = 1; //unsigned long long temp=1; //for (int j = 2; j <= 7.5e6; j++) //{ // temp = (temp * j) % 998244353; // arr[j] = temp; //} //for (int i = 1; i <= T; i++) //{ // scanf_s("%d", &n); // printf("%llu\n", arr[n]); //} //return 0; //E3E //int T; //scanf_s("%d", &T); //double sum1 = 0.000000; //double sum2 = 0.000000; //double sign = 1.0; //for (int i = 1; i <= 100000; i++) //{ // sum1 = sum1 + sign *1.000000/ (2 * i - 1); // sign = -sign; // arr1[i] = sum1; //} //for (int i = 1; i <= 100000; i++) //{ // sum2 = sum2 + 1.000000 / (long long)((long long)(2 * i - 1) * (long long)(2 * i - 1)); // arr2[i] = sum2; //} //for (int i = 1; i <= 100000; i++) //{ // Arr[i] = arr1[i] * 4 - sqrt(8 * arr2[i]); //} //int arrn[1000]; //int arrN[1000]; //for (int j = 1; j <= T; j++) //{ // scanf_s("%d", &arrn[j]); // arrN[j] = arrn[j]; //} //for (int k = 1; k <= T; k++) //{ // printf("%.6lf\n", fabs(Arr[arrN[k]])); //} //return 0; //E3F? //int n; //int a; //scanf_s("%d", &n); //for (int i = 1; i <= n; i++) //{ // scanf_s("%d", &a); // arrn[i] = a; //} //for (int j = 1; j <= 10000; j++) //{ // for (int k = 1; k <= 1000000; k++) // { // if (j == arrn[k]) // { // arr[j]++; // } // } // if (arr[j] != 0) // { // printf("%d : %d\n", j, arr[j]); // } //} //return 0; //E3F //int n; //scanf_s("%d", &n); //for (int i = 1; i <= n; i++) //{ // scanf_s("%d",&arr[i]); // arrn[arr[i]]++; //} //for (int i = 1; i <= 10000; i++) //{ // if (arrn[i] > 0) // { // printf("%d : %d\n", i, arrn[i]); // } //} //E3G? //int m, n; //int x0, y0; //int x, y; //scanf_s("%d%d", &n, &m); //scanf_s("%d%d", &x0, &y0); //scanf_s("%d%d", &x, &y); //for (int xi = 1; xi <= n; xi++) //{ // for (int yi = 1; yi <= m; yi++) // { // printf("0"); // } // printf("0\n"); //} //E3G! //long long n, m; //long long x0, y0; //long long x, y; //scanf_s("%lld%lld", &n,& m); //scanf_s("%lld%lld", &x0, &y0); //scanf_s("%lld%lld", &x, &y); //for (long long i = x - 2; i <= x + 2; i++) //{ // for (long long j = y - 2; j <= y + 2; j++) // { // if (i == x0 && j == y0) // { // printf("+"); // } // else if (i == x0 && j != y0) // { // printf("-"); // } // else if (i != x0 && j == y0) // { // printf("|"); // } // else if (i - x0 == j - y0) // { // printf("\\"); // } // else if (i - x0 == y0 - j) // { // printf("/"); // } // else if (i - x0 < 0 && j - y0>0 && x0 - i > j - y0) // { // printf("A"); // } // else if (i < x0 && j > y0 && x0 - i < j - y0) // { // printf("B"); // } // else if (i > x0 && j > y0 && i - x0 < j - y0) // { // printf("C"); // } // else if (i > x0 && j > y0 && i - x0 > j - y0) // { // printf("D"); // } // else if (i > x0 && j < y0 && i - x0 > y0 - j) // { // printf("E"); // } // else if (i > x0 && j < y0 && i - x0 < y0 - j) // { // printf("F"); // } // else if (i < x0 && j < y0 && i - x0 < j - y0) // { // printf("H"); // } // else // { // printf("G"); // } // } // printf("\n"); //} //return 0; //E3H? //int n; //scanf_s("%d", &n); //int y, m, d, h, mi; //for (int i = 1; i <= n; i++) //{ // scanf_s("%d.%d.%d %d:%d", &y, &m, &d, &h, &mi); //} //E3H! //int n; //scanf_s("%d", &n); //while (n--) //{ // int y, m, d, h, mi; // scanf_s("%d.%d.%d %d:%d", &y, &m, &d, &h, &mi); // while (mi >= 60) // { // mi = mi - 60; // h++; // } // while (h >= 24) // { // h = h - 24; // d++; // } // while (1) // { // while (m > 12) // { // m = m - 12; // y++; // } // int DD = D(y, m); // if (d <= DD) // { // break; // } // d = d - DD; // m++; // } // if (y >= 10000) // { // printf("%05d.%02d.%02d %02d:%02d\n", y, m, d, h, mi); // } // else // { // printf("%04d.%02d.%02d %02d:%02d\n", y, m, d, h, mi); // } //} //return 0; //E3I? //long long a, b, n; //scanf_s("%lld%lld%lld", &a, &b, &n); //long long ZHENG = a / b; //long long XIAO = a % b; //long long arr[110] = {0}; //for (int i = 1; i <= n + 1; i++) //{ // XIAO = XIAO * 10; // long long A = XIAO / b; // XIAO = XIAO % b; // arr[i] = A; //} //if (arr[n + 1] >= 5) //{ // arr[n]++; // for (int i = n; i >= 2; i--) // { // if (arr[i] >= 10) // { // arr[i] = arr[i] - 10; // arr[i - 1]++; // } // } // if (arr[1] >= 10) // { // arr[1] = arr[1] - 10; // ZHENG++; // } //} //printf("%lld.", ZHENG); //for (int i = 1; i <= n; i++) //{ // printf("%lld", arr[i]); //} //printf("\n"); //return 0; //E3K //int a, b; //scanf_s("%d%d", &a, &b); //double down= floor(a * 1.000000 / b); //double up = ceil(a * 1.000000 / b); //if (down == 0.0) //{ // down = 0.0; //} //if (up == 0.0) //{ // up = 0.0; //} //printf("%.lf %.lf", down, up); //return 0; //E3L? //int T; //int a; //scanf_s("%d", &T); //for (int i = 1; i <= T; i++) //{ // scanf_s("%d", &a); // if (a % 6 == 0) // { // printf("Tom wins\n"); // } // else // { // printf("Jerry wins\n"); // } //} //return 0; //E3M int T; scanf_s("%d", &T); int a1, b1, c1, d1, a2, b2, c2, d2; for (int i = 1; i <= T; i++) { scanf_s("%d%d%d%d%d%d%d%d", &a1, &b1, &c1, &d1, &a2, &b2, &c2, &d2); float X1 = (a1 + c1) * 1.0f / 2; float X2 = (a2 + c2) * 1.0f / 2; float Y1 = (d1 + b1) * 1.0f / 2; float Y2 = (d2 + b2) * 1.0f / 2; float rx1 = fabs(a1 - c1) * 1.0f / 2; float rx2 = fabs(a2 - c2) * 1.0f / 2; float ry1 = fabs(d1 - b1) * 1.0f / 2; float ry2 = fabs(d2 - b2) * 1.0f / 2; float dX = fabs(X1 - X2)*1.0f; float dY = fabs(Y1 - Y2)*1.0f; float S1 = 4 * rx1 * ry1*1.0f; float S2 = 4 * rx2 * ry2*1.0f; float SS = S1 + S2; float TT = fabs(Max(a1, a2) - Min(c1, c2)) * fabs(Min(d1, d2) - Max(b1, b2)); float dst = SS - TT; if (TT < 0.0f) { TT = 0.0f; } if (SS - TT < 0.0f) { dst= 0.0f; } if (dX < rx1 + rx2 && dY < ry1 + ry2) { printf("%d %d\n", (int)round(TT), (int)round(dst)); } else { printf("%d %d\n", 0, (int)round(dst)); } } return 0; //E3Y //int n; //int arr[22]; //scanf_s("%d", &n); //for (int i = 1; i <= n; i++) //{ // scanf_s("%d", &arr[i]); //} //int max = 0; //int Max = 0; //int min = 100; //int Min = 0; //for (int i = 1; i <= n; i++) //{ // if (arr[i] > max) // { // max = arr[i]; // Max = i; // } // if (arr[i] < min) // { // min = arr[i]; // Min = i; // } //} //arr[Min] = 0; //arr[Max] = 0; //double sum = 0.0; //double ave = 0.0; //for (int i = 1; i <= n; i++) //{ // sum = sum + arr[i]; //} //ave= sum / (n - 2); //int cut = ave * 100; //double decut = cut * 1.00 / 100; //printf("%.2lf", decut); //return 0; }WA为什么
最新发布
10-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值