zoukankan      html  css  js  c++  java
  • [BZOJ2724][Violet 6]蒲公英

    [BZOJ2724][Violet 6]蒲公英

    试题描述

    输入

    修正一下

    l = (l_0 + x - 1) mod n + 1, r = (r_0 + x - 1) mod n + 1

    输出

    输入示例

    6 3
    1 2 3 2 1 2
    1 5
    3 6
    1 5

    输出示例

    1
    2
    1

    数据规模及约定

    修正下:

    n <= 40000, m <= 50000

    题解

    分块,先预处理出 f[i][j] 表示第 i 块到第 j 块的众数,枚举起点 i 然后扫一遍就好了。

    其次是询问,对于一个询问 [ql, qr],其中 ql 属于块 l,qr 属于块 r,众数要么是 f[l+1][r-1],要么是不完整块中的数,所以我们需要搞一个 calc(l, r, x) 功能,表示询问 [l, r] 中 x 出现的次数,有了这个功能后就可以做到把答案初始设为 f[l+1][r-1](O(1)),然后 O(sqrt(n)) 暴力枚举不完整块中的数,如果出现次数比当前的多,就更新答案。

    这个 calc() 函数可以这样搞:把所有数离散,每个数的位置记下来,然后当询问 calc(l, r, x) 在 x 的位置序列上二分一下就可以计算了。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
        if(Head == Tail) {
            int l = fread(buffer, 1, BufferSize, stdin);
            Tail = (Head = buffer) + l;
        }
        return *Head++;
    }
    int read() {
        int x = 0, f = 1; char c = Getchar();
        while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
        while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
        return x * f;
    }
    
    #define maxn 40010
    #define maxq 210
    int n, m, num[maxn], A[maxn], st[maxq], en[maxq], bl[maxn], cntb, f[maxq][maxq], cntn[maxn];
    
    vector <int> pos[maxn];
    int calc(int l, int r, int x) {
    	return upper_bound(pos[x].begin(), pos[x].end(), r) - lower_bound(pos[x].begin(), pos[x].end(), l);
    }
    int query(int ql, int qr) {
    	int l = bl[ql], r = bl[qr];
    	if(r - l <= 1) {
    		int ans = A[ql], mx = calc(ql, qr, ans);
    		for(int i = ql + 1; i <= qr; i++) {
    			int tmp = calc(ql, qr, A[i]);
    			if(mx < tmp || (mx == tmp && ans > A[i])) ans = A[i], mx = tmp;
    		}
    		return ans;
    	}
    	int ans = f[l+1][r-1], mx = calc(ql, qr, ans);
    	for(int i = ql; i <= en[l]; i++) {
    		int tmp = calc(ql, qr, A[i]);
    		if(mx < tmp || (mx == tmp && ans > A[i])) ans = A[i], mx = tmp;
    	}
    	for(int i = st[r]; i <= qr; i++) {
    		int tmp = calc(ql, qr, A[i]);
    		if(mx < tmp || (mx == tmp && ans > A[i])) ans = A[i], mx = tmp;
    	}
    	return ans;
    }
    
    int main() {
    	n = read(); m = read();
    	int siz = (int)sqrt(n + .5);
    	for(int i = 1; i <= n; i++) {
    		num[i] = A[i] = read();
    		int p = (i - 1) / siz + 1; cntb = p;
    		if(!st[p]) st[p] = i;
    		en[p] = i;
    		bl[i] = p;
    	}
    	
    	sort(num + 1, num + n + 1);
    	for(int i = 1; i <= n; i++) A[i] = lower_bound(num + 1, num + n + 1, A[i]) - num;
    	for(int i = 1; i <= cntb; i++) {
    		memset(cntn, 0, sizeof(cntn));
    		for(int j = st[i]; j <= n; j++) {
    			cntn[A[j]]++;
    			int r = bl[j];
    			if(r > i && !f[i][r]) f[i][r] = f[i][r-1];
    			if(!f[i][r] || cntn[f[i][r]] < cntn[A[j]] || (cntn[f[i][r]] == cntn[A[j]] && f[i][r] > A[j]))
    				f[i][r] = A[j];
    		}
    	}
    	for(int i = 1; i <= n; i++) pos[A[i]].push_back(i);
    	
    	int x = 0;
    	while(m--) {
    		int l = (read() + x - 1) % n + 1, r = (read() + x - 1) % n + 1;
    		if(l > r) swap(l, r);
    		int tmp = query(l, r);
    		printf("%d
    ", num[tmp]);
    		x = num[tmp];
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    Tkinter之布局管理pack
    Python smtplib,email
    PyAutoGUI (2) 屏幕处理和弹框,输入中文
    键鼠操作自动化库--PyAutoGUI模块(1)
    python----->>删除超过固定天数的日志
    Transformer再下一城!Swin-Unet:首个纯Transformer的医学图像分割网络
    西门子S7-1200 PLC 水箱水位控制程序案例
    【开源】Transformer 在CV领域全面开花:新出跟踪、分割、配准等总结
    Google发布语义分割新数据集!顺带开发个模型屠榜,已被CVPR2021接收
    YOLOv5算什么,这个才是最强!---PP-YOLOv2
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/5795778.html
Copyright © 2011-2022 走看看