P5445 [APIO2019]路灯

咕了有点久的题。

维护颜色段是个显然的想法。

发现对于一次修改操作无非就是颜色段合并/分裂。

又有一个显然的想法,对于点对之间的关系,考虑 (a,b) 抽象到二维平面。

发现事实上对于合并/分裂都是矩形操作,查询就是单点操作。

考虑如何维护这个单点查,直接暴力做是废的,发现只需要考虑操作到这个点的操作即可。

发现联通时间抽象到时间轴上都是连通块,考虑维护一个后缀时间即可。

(a,b) 当前联通了,那么之后都会联通,当前不连通了,那么之后都不会联通。即一个后缀一维的东西,用总时间减下即可。

在机房花 15 min 实现了维护连通块的 set,加上维护二维平面的 DS 即可。

随手写了个大常数的 BIT 套 BIT,3log 只能 81 分。

可以换成别的二维数点结构,比如区间加转差分单点查之类的。

#include <bits/stdc++.h> #define int long long using namespace std; int rd() { int f=1,sum=0; char ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();} return sum*f; } #define N (int)(3e5+5) struct node { int l,r; node() { } node(int nl,int nr) { l=nl; r=nr; } bool operator < (const node &rhs) const { return r<rhs.r; } }; set<node>s; bool a[N]; int n,q,tim,nwans; bool rdd() { char ch=getchar(); while(!isdigit(ch)) ch=getchar(); return ch-'0'; } char rdc() { char ch=getchar(); while(!isalpha(ch)) ch=getchar(); return ch; } int lowbit(int x) { return x&(-x); } unordered_map<int,int>f[N]; void uptf(int id,int x,int v) { while(x<=n) f[id][x]+=v,x+=lowbit(x); } int qryf(int id,int x) { int res=0; while(x) res+=f[id][x],x-=lowbit(x); return res; } void upt(int x,int y,int v) { if(!x||!y) return ; while(x<=n) uptf(x,y,v),x+=lowbit(x); } int qry(int x,int y) { if(!x||!y) return 0; int res=0; while(x) res+=qryf(x,y),x-=lowbit(x); return res; } void update(int x,int y,int xx,int yy,int v) { upt(x,y,v); upt(x,yy+1,-v); upt(xx+1,y,-v); upt(xx+1,yy+1,v); } int query(int x,int y) { if(x>y) return tim; return qry(x,y); } void sins(int x,int y) { s.insert(node(x,y)); update(x,x,y,y,q-tim); } void sdel(int x,int y) { update(x,x,y,y,tim-q); } bool check(int x,int y) { if(x==y) return 1; --y; auto qwq=s.lower_bound(node(0,x)); if(qwq==s.end()) return 0; if((*qwq).l<=x&&y<=(*qwq).r) return 1; return 0; } void DEE() { for(auto x=s.begin();x!=s.end();++x) cout<<(*x).l<<" "<<(*x).r<<'\n'; } void ins(int x) { if(s.empty()) { sins(x,x); return ; } if(s.size()==1) { auto qwq=s.begin(); int al=(*qwq).l,ar=(*qwq).r; if(ar+1==x) { s.erase(qwq); sdel(al,ar); sins(al,x); } else if(al-1==x) { s.erase(qwq); sdel(al,ar); sins(x,ar); } else { sins(x,x); } return ; } auto L=s.lower_bound(node(0,x)); if(L==s.end()) { auto pre=s.end(); --pre; if(pre->r+1==x) { int pl=pre->l,pr=pre->r; s.erase(pre); sdel(pl,pr); sins(pl,x); } else { sins(x,x); } } else if(L!=s.begin()) { auto R=L; --L; int al=(*L).l,ar=(*L).r,bl=(*R).l,br=(*R).r; if(ar+1==x) { if(bl-1==x) { s.erase(L); s.erase(R); sdel(al,ar); sdel(bl,br); sins(al,br); } else { sdel(al,ar); s.erase(L); sins(al,x); } } else { if(bl-1==x) { sdel(bl,br); s.erase(R); sins(x,br); } else { sins(x,x); } } } else { int al=(*L).l,ar=(*L).r; if(al-1==x) { s.erase(L); sdel(al,ar); sins(x,ar); } else { sins(x,x); } } } void del(int x) { auto R=s.lower_bound(node(0,x)); int al=R->l,ar=R->r; sdel(al,ar); s.erase(R); if(al<=x-1) sins(al,x-1); if(x+1<=ar) sins(x+1,ar); } signed main() { n=rd(); q=rd(); for(int i=1;i<=n;i++) { a[i]=rdd(); if(a[i]) ins(i); } for(tim=1;tim<=q;tim++) { if(rdc()=='t') { int x=rd(); if(a[x]) del(x); else ins(x); a[x]^=1; // DE(); } else { int x=rd(),y=rd(); printf("%lld\n",query(x,y-1)-(check(x,y)?q-tim:0)); } } return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/15935716.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(65)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示