codeforces 522D. Closest Equals 线段树+离线

题目链接

n个数m个询问, 每次询问输出给定区间中任意两个相同的数的最近距离。

先将询问读进来, 然后按r从小到大排序, 将n个数按顺序插入, 并用map统计之前是否出现过, 如果出现过, 就更新线段树。

如果当前的i等于某个询问的r, 那么就查询, 具体看代码。

  1 #include <iostream>
  2 #include <vector>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <algorithm>
  6 #include <cmath>
  7 #include <map>
  8 #include <set>
  9 #include <string>
 10 #include <queue>
 11 #include <stack>
 12 #include <bitset>
 13 using namespace std;
 14 #define pb(x) push_back(x)
 15 #define ll long long
 16 #define mk(x, y) make_pair(x, y)
 17 #define lson l, m, rt<<1
 18 #define mem(a) memset(a, 0, sizeof(a))
 19 #define rson m+1, r, rt<<1|1
 20 #define mem1(a) memset(a, -1, sizeof(a))
 21 #define mem2(a) memset(a, 0x3f, sizeof(a))
 22 #define rep(i, n, a) for(int i = a; i<n; i++)
 23 #define fi first
 24 #define se second
 25 typedef pair<int, int> pll;
 26 const double PI = acos(-1.0);
 27 const double eps = 1e-8;
 28 const int mod = 1e9+7;
 29 const int inf = 1061109567;
 30 const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
 31 const int maxn = 5e5+5;
 32 int minn[maxn<<2], a[maxn], ans1[maxn], ans;
 33 struct node
 34 {
 35     int l, r, id;
 36     bool operator < (node a)const
 37     {
 38         if(r == a.r)
 39             id<a.id;
 40         return r<a.r;
 41     }
 42 }q[maxn];
 43 map <int, int> mp;
 44 void pushUp(int rt) {
 45     minn[rt] = min(minn[rt<<1], minn[rt<<1|1]);
 46 }
 47 void update(int p, int val, int l, int r, int rt) {
 48     if(l == r) {
 49         minn[rt] = val;
 50         return ;
 51     }
 52     int m = l+r>>1;
 53     if(p<=m)
 54         update(p, val, lson);
 55     else
 56         update(p, val, rson);
 57     pushUp(rt);
 58 }
 59 void query(int L, int R, int l, int r, int rt) {
 60     if(L<=l&&R>=r) {
 61         ans = min(ans, minn[rt]);
 62         return ;
 63     }
 64     int m = l+r>>1;
 65     if(L<=m)
 66         query(L, R, lson);
 67     if(R>m)
 68         query(L, R, rson);
 69 }
 70 int main()
 71 {
 72     int n, m;
 73     cin>>n>>m;
 74     for(int i = 1; i<=n; i++)
 75         scanf("%d", &a[i]);
 76     for(int i = 0; i<m; i++) {
 77         scanf("%d%d", &q[i].l, &q[i].r);
 78         q[i].id = i;
 79     }
 80     sort(q, q+m);
 81     int pos = 0;
 82     mem2(minn);
 83     for(int i = 1; i<=n; i++) {
 84         if(mp[a[i]]) {
 85             update(mp[a[i]], i-mp[a[i]], 1, n, 1);
 86         }
 87         mp[a[i]] = i;
 88         while(i == q[pos].r) {
 89             ans = inf;
 90             query(q[pos].l, i, 1, n, 1);
 91             if(ans == inf)
 92                 ans = -1;
 93             ans1[q[pos].id] = ans;
 94             pos++;
 95         }
 96     }
 97     for(int i = 0; i<m; i++)
 98         cout<<ans1[i]<<" ";
 99     return 0;
100 }
时间: 2024-10-10 16:13:22

codeforces 522D. Closest Equals 线段树+离线的相关文章

$Codeforces\ 522D\ Closest\ Equals$ 线段树

正解:线段树 解题报告: 传送门$QwQ$ 题目大意是说给定一个数列,然后有若干次询问,每次询问一个区间内相同数字之间距离最近是多少$QwQ$.如果不存在相同数字输出-1就成$QwQ$ 考虑先预处理出每个点的$pre$和$lst$,就前一个相同数字的位置和后一个相同数字的位置$QwQ$,然后在线段树上维护下每个点到达前一个相同数字的最短距离 然后对询问按左端点排序,每次查询右端点区间内的$min$就成,然后删去数的话就把它后一个数字的那个最短距离$update$成$inf$就成鸭$QwQ$ 然后

Codeforces 522D Closest Equals

题解: 傻逼题 直接从左向右扫描每个点作为右端点 然后单点修改区间查询就行了 另外一种更直观的做法就是$(i,j)$之间产生了$(j-i)$ 于是变成矩形查最大值,kd-tree维护 代码: #include <bits/stdc++.h> #define rint register int #define IL inline #define rep(i,h,t) for (int i=h;i<=t;i++) #define dep(i,t,h) for (int i=t;i>=h

Super Mario(线段树离线区间k值)

以前见过这题,没做出来,知道是离线处理,这次仔细想了下, 首先把出现的高度都map离散化一下,以离散化出来的数目g建树,把每个位置都开俩个vector,一个存以这个位置为L的询问,一个存以这个位置为R的询问. 然后从1-g 进行更新,假如当前i是以第j个区间的开始位置,那么这时就可以询问一下<=p[j].h的个数s,显然这时第J个区间多加的,需要减掉,p[j].sum-=s; 然后更新第i个数,update(a[i],1,g,1);再找到某第k区间是以i结尾的,那么依旧询问一下,得出s,p[k]

线段树+离线 hdu5654 xiaoxin and his watermelon candy

传送门:点击打开链接 题意:一个三元组假设满足j=i+1,k=j+1,ai<=aj<=ak,那么就好的.如今告诉你序列.然后Q次询问.每次询问一个区间[l,r],问区间里有多少个三元组满足要求 思路:刚開始看错题目了,原来三元组是连续3个,这作为bc最后一题也太水了把. . . 先一遍预处理.把连续3个满足条件的找出来,放到还有一个数组里排序去重,用这个数组来给三元组哈希.再扫一遍给三元组在之前那个排序好的数组里二分一下得到下标,大概就是哈希一下,用一个数字来表示. 之后的查询.事实上就是.在

gcd(线段树离线处理)——HDU 4630

对应HDU题目:点击打开链接 No Pain No Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1801    Accepted Submission(s): 770 Problem Description Life is a game,and you lose it,so you suicide. But you can

[Codeforces 1295E]Permutation Separation(线段树+贪心)

[Codeforces 1295E]Permutation Separation(线段树+贪心) 题面 给出一个排列\(p_1,p_2,...p_n\).初始时你需要选择一个位置把排列分成左右两个.然后在两个序列间移动元素使得左边序列的所有元素都比右边的所有元素小.给出每个元素\(p_i\)从一个序列移动到另一个序列的代价\(a_i\). 分析 显然最后得到的序列是小的数在一边,大的数在另一边.设从值为\(i\)的元素处分开之后移动代价为\(ans_i\). 一开始假设所有数都移到右边序列,那么

Codeforces Round #207 (Div. 1) A. Knight Tournament (线段树离线)

题目:http://codeforces.com/problemset/problem/356/A 题意:首先给你n,m,代表有n个人还有m次描述,下面m行,每行l,r,x,代表l到r这个区间都被x所击败了(l<=x<=r),被击败的人立马退出游戏让你最后输出每个人是被谁击败的,最后那个胜利者没被 人击败就输出0 思路:他的每次修改的是一个区间的被击败的人,他而且只会记录第一次那个被击败的人,用线段树堕落标记的话他会记录最后一次的,所以我们倒着来修改, 然后因为那个区间里面还包含了自己,在线段

F - One Occurrence CodeForces - 1000F (线段树+离线处理)

You are given an array aa consisting of nn integers, and qq queries to it. ii-th query is denoted by two integers lili and riri. For each query, you have to find any integer that occurs exactly once in the subarray of aa from index lili to index riri

SPOJ--K-query (线段树离线) 离线操作解决一下问题

K-query Given a sequence of n numbers a1, a2, ..., an and a number of k- queries. A k-query is a triple (i, j, k) (1 ≤ i ≤ j ≤ n). For each k-query (i, j, k), you have to return the number of elements greater than k in the subsequence ai, ai+1, ...,