BZOJ 4320 Homework

首先要想清楚一定是按根号分块。对于<根号的直接记录。>根号的怎么办呢?

设查询的是%y。

那么我们只要找一个0,y,2y,3y.....的lowerbound就好了。而这是根号的。到此总复杂度n√nlogn,无法通过此题。

怎么办呢?可以考虑离线。我们维护并查集,每个点的祖先是在数轴上它的右边第一个出现的数。

那么倒着做就是删数,就可以合并两个集合,就好了。复杂度n√nα(n)。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 400500
#define inf 1000000007
using namespace std;
int n,x;char s[5];
int mn[maxn],father[maxn],a[maxn],tot=0,mx[maxn];
struct query
{
    int type,x,ans;
    query (int type,int x,int ans):type(type),x(x),ans(ans) {}
    query () {}
}q[maxn];
int getfather(int x)
{
    if (x!=father[x]) father[x]=getfather(father[x]);
    return father[x];
}
void unionn(int x,int y)
{
    if (y>300000) return;
    int f1=getfather(x),f2=getfather(y);
    if (f1!=f2) father[f1]=f2;
}
int main()
{
    scanf("%d",&n);
    int top=(int)sqrt(300000)+1;
    for (int i=1;i<=top;i++) mn[i]=inf;
    for (int i=1;i<=n;i++)
    {
        mx[i]=mx[i-1];
        scanf("%s",s);scanf("%d",&x);
        if (s[0]==‘A‘) q[i]=query(1,x,0);
        else q[i]=query(2,x,0);
        if (s[0]==‘A‘)
        {
            for (int j=1;j<=top;j++)
                mn[j]=min(mn[j],x%j);
            a[++tot]=x;mx[i]=max(mx[i],x);
        }
        else if (x<=top) q[i]=query(2,x,mn[x]);
    }
    sort(a+1,a+tot+1);for (int i=1;i<=300000;i++) father[i]=i;
    int p=1;
    for (int i=1;i<=300000;i++)
    {
        if (a[p]<i) p++;
        father[i]=a[p];
    }
    for (int i=n;i>=1;i--)
    {
        if (q[i].type==1) unionn(q[i].x,q[i].x+1);
        else if (q[i].x>top)
        {
            int ret=inf,kr=q[i].x;
            for (int j=q[i].x;j<=mx[i];j+=q[i].x)
            {
                int f=getfather(j);
                ret=min(ret,f%q[i].x);
            }
            ret=min(ret,getfather(1)%q[i].x);
            q[i]=query(2,kr,ret);
        }
    }
    for (int i=1;i<=n;i++)
        if (q[i].type==2) printf("%d\n",q[i].ans);
    return 0;
}
时间: 2024-10-21 04:55:12

BZOJ 4320 Homework的相关文章

BZOJ 4320 ShangHai2006 Homework

题意: 给出N(<=1e5)个操作,操作分为两种,①在集合中添加一个数x,②问这个集合中mod x 的最小值是多少.(x <= 3e5) 题解: 0.首先我们发现log家族中有算法满足这道题目,那么采用分块的思想. 1.那么对于小于根号下MAX(x)的询问,直接暴力维护答案,对于大于根号MAX(x)的询问,只需要找到第一个大于等于K * x 的值是多少. 2.那么现在问题是维护第一个大于等于K * x 的值是多少,现在有两种选择,①用STL中的<set> 中的 lower_boun

bzoj 4320: ShangHai2006 Homework【分块】

按根号300000=m分情况讨论 查询是,当x小于等于m,那么可以暴力记录直接出解:否则,用分块维护区间值,查询的时候以x为步长跳根号m次取最小值即可 还有一种并查集方法,来自https://www.cnblogs.com/CQzhangyu/p/7088337.html #include<iostream> #include<cstdio> using namespace std; const int N=300010,M=550; int n=300000,m=n/M,q,i,

4320: ShangHai2006 Homework

4320: ShangHai2006 Homework 链接 分析: 分块.对权值模数进行分块,模数小于$\sqrt V$的($V$为权值上界),暴力处理. 模数大于$\sqrt V$的,设模数是k,枚举k的倍数,然后查询大于[k,2k]之间的最小的数x,这个区间的mod k最小的数就是x-k.k的倍数共有$\sqrt V$个,每次查询,再对权值进行分块,并维护后缀最小值,做到$O(1)$查询.复杂度$O(n \sqrt V)$ 代码: #include<cstdio> #include<

BZOJ 3379: [Usaco2004 Open]Turning in Homework 交作业

Description 贝茜有C(1≤C≤1000)门科目的作业要上交,之后她要去坐巴士和奶牛同学回家. 每门科目的老师所在的教室排列在一条长为H(1≤H≤1000)的走廊上,他们只在课后接收作业.交作业不需要时间.贝茜现在在位置0,她会告诉你每个教室所在的位置,以及走廊出口的位置.她每走1个单位的路程,就要用1秒.她希望你计算最快多久以后她能交完作业并到达出口. Input 第1行输入三个整数C,H,B,B是出口的位置.之后C行每行输入两个整数,分别表示一个老师所在的教室和他的下课时间. Ou

BZOJ 1013: [JSOI2008]球形空间产生器sphere

二次联通门 : BZOJ 1013: [JSOI2008]球形空间产生器sphere /* BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元 QAQ SB的我也能终于能秒题了啊 设球心的坐标为(x,y,z...) 那么就可以列n+1个方程,化化式子高斯消元即可 */ #include <cstdio> #include <iostream> #include <cstring> #define rg register #define Max

bzoj 3309 DZY Loves Math - 莫比乌斯反演 - 线性筛

对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0. 给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b). Input 第一行一个数T,表示询问数. 接下来T行,每行两个数a,b,表示一个询问. Output 对于每一个询问,输出一行一个非负整数作为回答. Sample Input 4 7558588 9653114 6514903 445

【BZOJ】[HNOI2009]有趣的数列

[算法]Catalan数 [题解] 学了卡特兰数就会啦>_<! 因为奇偶各自递增,所以确定了奇偶各自的数字后排列唯一. 那么就是给2n个数分奇偶了,是不是有点像入栈出栈序呢. 将做偶数标为-1,做奇数标为+1,显然当偶数多于奇数时不合法,因为它压不住后面的奇数. 然后其实这种题目,打表就可知啦--QAQ 然后问题就是求1/(n+1)*C(2n,n)%p了,p不一定是素数. 参考bzoj礼物的解法. 看到网上清一色的素数筛+分解质因数解法,不解了好久,感觉写了假的礼物-- 后来觉得礼物的做法才比

洛谷 P2709 BZOJ 3781 小B的询问

题目描述 小B有一个序列,包含N个1~K之间的整数.他一共有M个询问,每个询问给定一个区间[L..R],求Sigma(c(i)^2)的值,其中i的值从1到K,其中c(i)表示数字i在[L..R]中的重复次数.小B请你帮助他回答询问. 输入输出格式 输入格式: 第一行,三个整数N.M.K. 第二行,N个整数,表示小B的序列. 接下来的M行,每行两个整数L.R. 输出格式: M行,每行一个整数,其中第i行的整数表示第i个询问的答案. 输入输出样例 输入样例#1: 6 4 3 1 3 2 1 1 3

BZOJ 1012: [JSOI2008]最大数maxnumber(线段树)

012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MB Description 现在请求你维护一个数列,要求提供以下两种操作:1. 查询操作.语法:Q L 功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值.限制:L不超过当前数列的长度.2. 插入操作.语法:A n 功能:将n加上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取模,将所得答案插入到数列