loj #3146. 「APIO 2019」路灯

loj #3146. 「APIO 2019」路灯

暴力的话就是查询\((l,r)\)之间是否全部是1,考虑如何优化查询

我们可以利用\(set\)来维护每一个全\(1\)区间和它出现的时间,具体的,用\((lp,rp,l,r)\)来表示\((lp,rp)\)的全\(1\)区间在时间\([l,r]\)中是存在的

那么对于一个在时间\(i\)的询问\((l_i,r_i)\),\((lp,rp,l,r)\)会对它产生贡献当且仅当\(lp\leq l_i,rp\geq r_i,i\geq l\),产生的贡献为\(min(i,r)-l+1\)

注意到限制的条件其实是类似于三维偏序的,将全\(1\)区间的四元组也当做询问,我们按照\(r\)值降序所有的询问,进行\(cdq\)分治

考虑前一半对后一半的贡献,两边分别按\(l\)升序排序,线段树维护这个类似区间长度的贡献即可

细节稍微有点小多,而且由于过度使用stl所以常数巨大

#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
const int N=10000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define fir first
#define sec second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define maxd 998244353
#define eps 1e-8
struct segnode{
    int lp,rp,l,r;
}seg[1200100];
struct qnode{
    int l,r,tim,id;
}q[300300];
struct tnode{
    int op,id,r;
}th[2002000];
int ans[300300];
int n,m,nowr[300300],id[300300],tot=0,sta[300300];
int tr[2002000],add[2002000],qtot=0,tot1=0;
set<int> nowl;
set<int>::iterator iter;
char s[300300],op[10];

int read()
{
    int x=0,f=1;char ch=getchar();
    while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
    while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
    return x*f;
}

void pushup(int id) {tr[id]=tr[id<<1]+tr[id<<1|1];}

void pushdown(int id,int l,int r)
{
    if (add[id])
    {
        int mid=(l+r)>>1;
        tr[id<<1]+=add[id]*(mid-l+1);
        tr[id<<1|1]+=add[id]*(r-mid);
        add[id<<1]+=add[id];add[id<<1|1]+=add[id];
        add[id]=0;
    }
}

void modify(int id,int l,int r,int ql,int qr,int val)
{
    //cout << l << " " << r << " " << ql << " " << qr << " " << val << endl;
    if ((l>=ql) && (r<=qr))
    {
        tr[id]+=val*(r-l+1);
        add[id]+=val;return;
    }
    pushdown(id,l,r);
    int mid=(l+r)>>1;
    if (ql<=mid) modify(id<<1,l,mid,ql,qr,val);
    if (qr>mid) modify(id<<1|1,mid+1,r,ql,qr,val);
    pushup(id);
}

int query(int id,int l,int r,int ql,int qr)
{
    if ((l>=ql) && (r<=qr)) return tr[id];
    int mid=(l+r)>>1,ans=0;pushdown(id,l,r);
    if (ql<=mid) ans+=query(id<<1,l,mid,ql,qr);
    if (qr>mid) ans+=query(id<<1|1,mid+1,r,ql,qr);
    return ans;
}

bool cmp1(tnode p,tnode q)
{
    if (p.r!=q.r) return p.r>q.r;
    else return p.op<q.op;
}

bool cmp2(tnode x,tnode y)
{
    if (x.op!=y.op) return x.op<y.op;
    else if (x.op==1) return seg[x.id].lp<seg[y.id].lp;
    else return q[x.id].l<q[y.id].l;
}

void solve(int l,int r)
{
    if (l==r) return;
    int mid=(l+r)>>1;
    solve(l,mid);solve(mid+1,r);
    sort(th+l,th+mid+1,cmp2);
    sort(th+mid+1,th+r+1,cmp2);
    int p=l;
    rep(i,mid+1,r)
    {
        if (th[i].op==1) continue;
        while ((p<=mid) && (th[p].op==1) && (q[th[i].id].l>=seg[th[p].id].lp))
        {
            modify(1,1,m,seg[th[p].id].l,seg[th[p].id].r,1);
            p++;
        }
        ans[th[i].id]+=query(1,1,m,1,q[th[i].id].tim);
    }
    rep(i,l,p-1) modify(1,1,m,seg[th[i].id].l,seg[th[i].id].r,-1);
}

int main()
{
    n=read();m=read();
    scanf("%s",s+1);
    rep(i,1,n) sta[i]=s[i]-'0';
    for (int i=1;i<=n;i++)
    {
        if (sta[i]==0) continue;
        int j=i;
        while ((j<=n) && (sta[j]==1)) j++;j--;
        nowr[i]=j;nowl.insert(i);
        id[i]=(++tot);
        seg[id[i]]=(segnode){i,j,1,m};i=j;
    }
    //for (iter=nowl.begin();iter!=nowl.end();iter++) cout << (*iter) << " ";cout << endl;
    //rep(i,1,n) cout << nowr[i] << " ";cout << endl;
    rep(i,1,m)
    {
        scanf("%s",op);
        if (op[0]=='t')
        {
            if (i==m) continue;
            int pos=read();sta[pos]^=1;
            if (sta[pos])
            {
                int l=pos,r=pos;
                iter=nowl.upper_bound(pos);
                if (iter!=nowl.end())
                {
                    int tmp=(*iter);
                    if (tmp==pos+1)
                    {
                        r=nowr[tmp];
                        seg[id[tmp]].r=i;nowl.erase(tmp);
                    }
                }
                iter=nowl.lower_bound(pos);
                if (iter!=nowl.begin())
                {
                    int tmp=*(--iter);
                    if (nowr[tmp]==pos-1)
                    {
                        l=tmp;
                        seg[id[tmp]].r=i;
                        nowl.erase(tmp);
                    }
                }
                id[l]=(++tot);nowr[l]=r;
                seg[id[l]]=(segnode){l,r,i+1,m};
                nowl.insert(l);
            }
            else
            {
                iter=nowl.upper_bound(pos);iter--;
                int l=(*iter),r=nowr[l];
                seg[id[l]].r=i;
                if (l<pos)
                {
                    id[l]=(++tot);
                    seg[id[l]]=(segnode){l,pos-1,i+1,m};
                    nowr[l]=pos-1;
                }
                else nowl.erase(l);
                if (r>pos)
                {
                    id[pos+1]=(++tot);
                    seg[id[pos+1]]=(segnode){pos+1,r,i+1,m};
                    nowr[pos+1]=r;nowl.insert(pos+1);
                }
            }
        }
        else
        {
            q[++qtot].id=qtot;q[qtot].tim=i;
            q[qtot].l=read();q[qtot].r=read()-1;
         }
    }
    //rep(i,1,qtot) cout << q[i].id << " " << q[i].l << " " << q[i].r << " " << q[i].tim << endl;
    rep(i,1,tot) th[++tot1]=(tnode){1,i,seg[i].rp};
    rep(i,1,qtot) th[++tot1]=(tnode){2,i,q[i].r};
    sort(th+1,th+1+tot1,cmp1);
    //rep(i,1,tot1) cout << th[i].id << " " << th[i].op << " " << th[i].r << endl;
    solve(1,tot1);
    rep(i,1,qtot) printf("%d\n",ans[i]);
    return 0;
}

/*
5 8
11011
query 1 2
query 1 2
query 1 6
query 3 4
toggle 3
query 3 4
toggle 2
query 1 6
 */            

原文地址:https://www.cnblogs.com/encodetalker/p/11105339.html

时间: 2024-08-30 14:39:13

loj #3146. 「APIO 2019」路灯的相关文章

loj #3144. 「APIO 2019」奇怪装置

loj #3144. 「APIO 2019」奇怪装置 很明显的是我们需要找到\((x,y)\)的循环节的长度 当\(t=0\)时,\(x=0,y=0\) 当\(t\neq 0\)时,仍然要使的\(x=0,y=0\)的话,必有 \[ \begin{cases} t+\lfloor \frac{t}{B} \rfloor \equiv0(mod\ A)\t\equiv0(mod\ B) \end{cases} \] 记\(t=t'B\),则有\(A|t'(B+1)\),故\(t'\)最小为\(\fr

#3144. 「APIO 2019」奇怪装置

#3144. 「APIO 2019」奇怪装置 题目描述 考古学家发现古代文明留下了一种奇怪的装置.该装置包含两个屏幕,分别显示两个整数 \(x\) 和 \(y\). 经过研究,科学家对该装置得出了一个结论:该装置是一个特殊的时钟,它从过去的某个时间点开始测量经过的时刻数 \(t\),但该装置的创造者却将 \(t\) 用奇怪的方式显示出来.若从该装置开始测量到现在所经过的时刻数为 \(t\),装置会显示两个整数:\(x = ((t + \lfloor \frac{t}{B} \rfloor) \b

路灯「APIO 2019」

题意 有.复杂,自己上网搜 思路 \((x,y)\) 表示从\(x\)到\(y\)联通的时间长度. 那么查询操作相当于二维平面上的单点查询. 对于每一个\(i\),维护一个最左能到达的\(lm\),和最右能到达的\(rm\). 那么对于每一个更新操作,相当于对左上角为\((lm,i)\),右下角为\((i,rm)\)的矩形做修改. 于是就转换为类似「简单题」的题目了,可以CDQ分治解决,当然也可以直接上树套树. 代码 #include <bits/stdc++.h> using namespa

loj 3217 「PA 2019」Desant - 动态规划 - 复杂度分析

题目传送门 传送门 一个非常显然的想法是记录后面的值相邻两个之间在前面选了多少个数. 众所周知(比如我就不知道,我甚至以为它非常大),若干个和为 $n$ 的数的乘积最大为 $O(3^{n/3})$,最优方案是拆成若干个 3 和常数个 2. 然后 dp 即可. 时间复杂度 $O(n^23^{\frac{n + 1}{3}})$. Code #include <bits/stdc++.h> using namespace std; typedef bool boolean; const int N

Loj #3085. 「GXOI / GZOI2019」特技飞行

Loj #3085. 「GXOI / GZOI2019」特技飞行 题目描述 公元 \(9012\) 年,Z 市的航空基地计划举行一场特技飞行表演.表演的场地可以看作一个二维平面直角坐标系,其中横坐标代表着水平位置,纵坐标代表着飞行高度. 在最初的计划中,这 \(n\) 架飞机首先会飞行到起点 \(x = x_{st}\) 处,其中第 \(i\) 架飞机在起点处的高度为 \(y_{i,0}\).它们的目标是终点 \(x = x_{ed}\) 处,其中第 \(i\) 架飞机在终点处的高度应为 \(y

loj 3014「JOI 2019 Final」独特的城市

loj 我本来是直接口胡了一个意思一样的做法的,但是因为觉得有点假+实现要用并查集(?)就卡了好一会儿... 对于一个点\(x\)来说,独特的点一定在它的最长链上,如果有独特的点不在最长链上,那么最长链上一定有和他到\(x\)距离相同的点,矛盾 然后对于一个点,最长链端点一定可以是直径的两端点之一,所以如果我们分别以树的直径的两端点为根进行dfs,那么一个点在其中一次dfs中,独特的点都会在到根的路径上,所以我们用栈维护到根的点,然后不同颜色数开桶来维护,每次压栈或弹栈时改变桶内元素个数,然后根

特别行动队「APIO 2010」

题意 有一个序列,要求将其分为任意部分.对于每一部分,其值为\(at^2+bt+c\),其中\(t\)为这一部分元素总和,\(a,b,c\)给定. 思路 容易推出状态转移方程为\(f[i]=min(f[j]+a*(sum[i]-sum[j])^2+b*(sum[i]-sum[j])+c)\) 朴素转移的时间复杂度为\(n^2\),考虑斜率优化. 假设对于决策点\(x,y\),存在\(f[x]+a*(sum[i]-sum[x])^2+b*(sum[i]-sum[x])+c>f[y]+a*(sum[

[LOJ#2325]「清华集训 2017」小Y和恐怖的奴隶主

[LOJ#2325]「清华集训 2017」小Y和恐怖的奴隶主 试题描述 "A fight? Count me in!" 要打架了,算我一个. "Everyone, get in here!" 所有人,都过来! 小Y是一个喜欢玩游戏的OIer.一天,她正在玩一款游戏,要打一个Boss. 虽然这个Boss有 \(10^{100}\) 点生命值,但它只带了一个随从--一个只有 \(m\) 点生命值的"恐怖的奴隶主". 这个"恐怖的奴隶主&qu

[LOJ#2328]「清华集训 2017」避难所

[LOJ#2328]「清华集训 2017」避难所 试题描述 "B君啊,你当年的伙伴都不在北京了,为什么你还在北京呢?" "大概是因为出了一些事故吧,否则这道题就不叫避难所了." "唔,那你之后会去哪呢?" "去一个没有冬天的地方." 对于一个正整数 \(n\),我们定义他在 \(b\) 进制下,各个位上的数的乘积为 \(p = F(n, b)\). 比如 \(F(3338, 10) = 216\). 考虑这样一个问题,已知 \