题目描述
恭喜你找到了本场比赛的签到题!
为了让大家都有抽奖的机会,只需要复制粘贴以下代码(并且稍微填下空)即可 AC:
(我超良心的)
#include <algorithm> #include <iostream> #include <cstring> #include <climits> #include <cstdio> #include <vector> #include <cstdlib> #include <ctime> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #define fi first #define lc (x<<1) #define se second #define U unsigned #define rc (x<<1|1) #define Re register #define LL long long #define MP std::make_pair #define CLR(i,a) memset(i,a,sizeof(i)) #define FOR(i,a,b) for(Re int i = a;i <= b;++i) #define ROF(i,a,b) for(Re int i = a;i >= b;--i) #define SFOR(i,a,b,c) for(Re int i = a;i <= b;i+=c) #define SROF(i,a,b,c) for(Re int i = a;i >= b;i-=c) #define DEBUG(x) std::cerr << #x << '=' << x << std::endl const int MAXN = 1000000+5; int N,maxL; std::set<std::pair<int,int> > L; inline int calc(){ // 返回 set 中所有线段的并长度。(每个 pair 表示一个线段[first,second] } int main(){ scanf("%d%d",&N,&maxL); while(N--){ int opt,x,y; scanf("%d%d%d",&opt,&x,&y); if(opt == 1){ if(L.find(MP(x,y)) != L.end()) continue; L.insert(MP(x,y)); } if(opt == 2){ if(L.find(MP(x,y)) == L.end()) continue; L.erase(MP(x,y)); } if(opt == 3){ printf("%d\n",calc()); } } return 0; }
输入描述:
第一行两个整数 N,L,意义如代码所述。
接下来 N 行,每行三个整数 opt,l,r,意义如代码所述。
输出描述:
对于每一组 opt=3 的询问输出一个答案。
题解
这里我们考虑用线段树的做,我们用a[N]表示节点表示的线段的覆盖次数( 不是和),b[N]表示节点表示的线段的答案,在添加时只需要将该线段在线段树中表示的线段标记加1,在删除的时候只需要将该线段在线段数中表示的线段标记减1,这样,如果要删去的线段为某一线段的子线段,那么删除后肯定能保证原线段在线段树中对应的线段标记至少为1,应为删除的线段在之前肯定添加过,这样就能保证答案的正确性。
附代码:
#include<bits/stdc++.h> using namespace std; typedef pair<int,int> pii; const int N = 1e7+5; int a[N<<2],b[N<<2]; set<pii>s; void updata(int x,int y,int z,int l,int r,int rat){ if(x<=l&&r<=y){ a[rat]+=z; if(a[rat])b[rat]=r-l+1; else if(l!=r)b[rat]=b[rat<<1]+b[rat<<1|1]; else b[rat]=0;//单点情况 return ; } int mid=(r+l)>>1; if(mid>=x) updata(x,y,z,l,mid,rat<<1); if(mid<y) updata(x,y,z,mid+1,r,rat<<1|1); if(a[rat])b[rat]=r-l+1; else if(l!=r)b[rat]=b[rat<<1]+b[rat<<1|1]; else b[rat]=0;//单点情况 } int main(){ int n,m; cin>>n>>m; while(n--){ int opt,x,y; cin>>opt>>x>>y; if(opt == 1){ if(s.find((pii){x,y}) != s.end()) continue; s.insert((pii){x,y}); updata(x,y,1,1,m,1); } if(opt == 2){ if(s.find((pii){x,y}) == s.end()) continue; s.erase((pii){x,y}); updata(x,y,-1,1,m,1); } if(opt == 3){ cout<<b[1]<<'\n'; } } return 0; }