CF915E Physical Education Lessons(动态开点线段树/珂朵莉树)
CF915E
题目大意(懒狗直接偷的题面):#
从现在到学期结束还有
- 如果
,那么从 到 (包含端点)的所有日子都变成非工作日。 - 如果
,那么从 到 (包含端点)的所有日子都变成工作日。
统计每个指令下发后,剩余的工作日天数。
输入格式:#
第一行一个整数
接下来
输出格式:#
输出
样例输入 #1#
4
6
1 2 1
3 4 1
2 3 2
1 3 2
2 4 1
1 4 2
样例输出 #1#
2
0
2
3
1
4
分析1:#
看到这题会想到常规线段树区间覆盖,但是发现数据范围
虽然如此,询问操作还是比较小的,说明提前建好的线段树某些区间几乎用不到,所以可利用动态开点,需要用到此区间的时候再将它建立。
代码1(线段树动态开点):#
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 16e6+10;
inline int read() {
char ch=getchar();
int f=1,x=0;
while(ch<'0'||ch>'9') {
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9') {
x=x*10+ch-'0';
ch=getchar();
}
return f*x;
}
int n,m,root=0;
int cnt;
struct T{
int l,r,val,lazy;
}t[MAXN];
int newnode(){
cnt++;
t[cnt].lazy=-1;
return cnt;
}
void update(int p){
t[p].val=t[t[p].l].val+t[t[p].r].val;
}
void pushdown(int l,int r,int p){
if(l==r||t[p].lazy==-1){
return;
}
if(!t[p].l){
t[p].l=newnode();
}
if(!t[p].r){
t[p].r=newnode();
}
int mid=(l+r)>>1;
t[t[p].l].val=(mid-l+1)*t[p].lazy;
t[t[p].r].val=(r-mid)*t[p].lazy;
t[t[p].l].lazy=t[p].lazy;
t[t[p].r].lazy=t[p].lazy;
t[p].lazy=-1;
}
void change(int l,int r,int &p,int x,int y,int k){
if(r<x||y<l) {
return ;
}
if(!p) p=newnode();
if(x<=l&&r<=y){
t[p].lazy=k;
t[p].val=(r-l+1)*k;
return;
}
pushdown(l,r,p);
int mid=(l+r)>>1;
change(l,mid,t[p].l,x,y,k);
change(mid+1,r,t[p].r,x,y,k);
//update(p);
t[p].val=t[t[p].l].val+t[t[p].r].val;
}
signed main(){
n=read();
m=read();
change(1,n,root,1,n,1);
for(int i=1;i<=m;i++){
int l,r,op;
l=read();
r=read();
op=read();
if(op==1){
change(1,n,root,l,r,0);
}
else{
change(1,n,root,l,r,1);
}
printf("%d\n",t[1].val);
}
return 0;
}
分析2:#
区间01赋值操作就是珂朵莉树的常规操作。
所以使用珂朵莉树就是一个较为模板的题。
代码2(珂朵莉树):#
#include<bits/stdc++.h>
#define ll long long
#define sit set<asd>::iterator
using namespace std;
inline ll read() {
ll x = 0, fh = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {
if (ch == '-')
fh = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * fh;
}
struct asd{
ll l,r;
mutable ll val;
bool operator < (const asd& A)const{return l<A.l;}
asd(ll aa,ll bb,ll cc){l=aa,r=bb,val=cc;}
asd(ll aa){l=aa;}
};
int sum=0;
ll n,m,maxn,seed;
set<asd>s;
sit split(ll wz){
sit it=s.lower_bound(asd(wz));
if(it!=s.end()&&it->l==wz)return it;
it--;
ll l=it->l;
ll r=it->r;
ll val=it->val;
s.erase(it);
s.insert(asd(l,wz-1,val));
return s.insert(asd(wz,r,val)).first;
}
void assign(int l,int r,bool val){
sit itr = split(r+1), itl = split(l), it = itl;
for( ;itl != itr; ++itl)
sum-=itl->val*(itl->r-itl->l+1);
s.erase(it,itr);
s.insert(asd(l,r,val));
sum+=val*(r-l+1);
}
signed main(){
n=read();
m=read();
s.insert(asd(1,n,1));
sum=n;
while(m--){
int l=read(),r=read(),op=read();
if(op==1){
assign(l,r,0);
}
else {
assign(l,r,1);
}
printf("%d\n",sum);
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】