CF915E Physical Education Lessons

CF915E Physical Education Lessons

 

Alex高中毕业了,他现在是大学新生。虽然他学习编程,但他还是要上体育课,这对他来说完全是一个意外。快要期末了,但是不幸的Alex的体育学分还是零蛋!

Alex可不希望被开除,他想知道到期末还有多少天的工作日,这样他就能在这些日子里修体育学分。但是在这里计算工作日可不是件容易的事情:

从现在到学期结束还有 $n$ 天(从 $1$ 到 $n$ 编号),他们一开始都是工作日。接下来学校的工作人员会依次发出 $q$ 个指令,每个指令可以用三个参数 $l,r,k$ 描述:

如果 $k=1$,那么从 $l$ 到 $r$ (包含端点)的所有日子都变成非工作日。

如果 $k=2$,那么从 $l$ 到 $r$ (包含端点)的所有日子都变成工作日。

帮助Alex统计每个指令下发后,剩余的工作日天数。

 

动态开点线段树模板题,又是一道水题

 

数据范围,又是熟悉的$1n10^9,1q3\times10^5$

 

动态开点线段树啦

 

调了半天,第$17$个点MLE,why?只好抄了篇不用指针写的版本

#include<bits/stdc++.h>

using namespace std;

int n,q;

struct node {
    int f,sum;
    node *lc,*rc;
    node() {
        sum=0,f=0,lc=rc=NULL;
    }
    void push_down(int l,int r) {
        if(!f) return;
        if(!lc) lc=new node();
        if(!rc) rc=new node();
        f--;
        int mid=(l+r)>>1;
        lc->f=f+1,rc->f=f+1;
        lc->sum=(mid-l+1)*f;
        rc->sum=(r-mid)*f;
        f=0;
    }
    void push_up(){
        sum=0;
        if(lc) sum+=lc->sum;
        if(rc) sum+=rc->sum;
    }
}*root=new node();

void insert(node *&cur){
    if(!cur) cur=new node();
}
void change(node *&cur,int l,int r,int ql,int qr,int val){
    if(!cur) cur=new node();
    if(l>=ql&&r<=qr) {cur->sum=(r-l+1)*val;cur->f=val+1;return;}
    cur->push_down(l,r);
    int mid=(l+r)>>1;
    if(qr<=mid) change(cur->lc,l,mid,ql,qr,val),insert(cur->rc);
    else if(ql>mid) change(cur->rc,mid+1,r,ql,qr,val),insert(cur->lc);
    else change(cur->lc,l,mid,ql,qr,val),change(cur->rc,mid+1,r,ql,qr,val);
    cur->push_up();
}

int main() {
    scanf("%d%d",&n,&q);
    root->sum=0;
    for(int l,r,k,i=1; i<=q; i++) {
        scanf("%d%d%d",&l,&r,&k);
        if(k==2) k=0;
        change(root,1,n,l,r,k);
        printf("%d\n",n-root->sum);
    }
    
    return 0;
}
MLE的指针版

 

敲好用

#include<bits/stdc++.h>

#define N 300000
using namespace std;

int n,q,tot,v[N*50],lson[N*50],rson[N*50],f[N*50],rt;

void insert(int &k){
    if(!k) {
        k=++tot;
        v[k]=0;
    }
}

void push_up(int k){
    v[k]=v[lson[k]]+v[rson[k]];
}

void push_down(int k,int l,int r){
    if(!f[k]) return;
    if(!lson[k]) lson[k]=++tot;
    if(!rson[k]) rson[k]=++tot;
    int mid=(l+r)>>1;
    --f[k];
    v[lson[k]]=(mid-l+1)*f[k];
    v[rson[k]]=(r-mid)*f[k];
    f[lson[k]]=f[k]+1;
    f[rson[k]]=f[k]+1;
    f[k]=0;
}

void insert(int &k,int l,int r,int ql,int qr,int val){
    if(!k) k=++tot;
    if(l>=ql&&r<=qr) {v[k]=(r-l+1)*val,f[k]=val+1;return;}
    push_down(k,l,r);
    int mid=(l+r)>>1;
    if(ql>mid) insert(rson[k],mid+1,r,ql,qr,val),insert(lson[k]);
    else if(qr<=mid) insert(lson[k],l,mid,ql,qr,val),insert(rson[k]);
    else insert(lson[k],l,mid,ql,qr,val),insert(rson[k],mid+1,r,ql,qr,val);
    push_up(k);
}

int main() {
    scanf("%d%d",&n,&q);
    rt=tot=1;
    for(int l,r,k,i=1; i<=q; i++) {
        scanf("%d%d%d",&l,&r,&k);
        if(k==2) k=0;
        insert(rt,1,n,l,r,k);
        printf("%d\n",n-v[rt]);
    }
    
    return 0;
}

由数组版的启发,写出了$AC$的指针版

虽然只是改动了赋新地址的方法而已,但是以后还是用这种方法吧,免得出麻烦

#include<bits/stdc++.h>

#define N 300000
using namespace std;

int n,q,tot;
struct node {
    int f,sum;
    node *lc,*rc;
}*root,x[N*50];
void push_down(node *cur,int l,int r) {
    if(!cur->f) return;
    if(!cur->lc) cur->lc=&x[++tot];
    if(!cur->rc) cur->rc=&x[++tot];
    cur->f--;
    int mid=(l+r)>>1;
    cur->lc->f=cur->f+1,cur->rc->f=cur->f+1;
    cur->lc->sum=(mid-l+1)*cur->f;
    cur->rc->sum=(r-mid)*cur->f;
    cur->f=0;
}
void push_up(node *cur){
    cur->sum=0;
    if(cur->lc) cur->sum+=cur->lc->sum;
    if(cur->rc) cur->sum+=cur->rc->sum;
}

void insert(node *&cur){
    if(!cur) cur=&x[++tot];
}
void change(node *&cur,int l,int r,int ql,int qr,int val){
    if(!cur) cur=&x[++tot];
    if(l>=ql&&r<=qr) {cur->sum=(r-l+1)*val;cur->f=val+1;return;}
    push_down(cur,l,r);
    int mid=(l+r)>>1;
    if(qr<=mid) change(cur->lc,l,mid,ql,qr,val),insert(cur->rc);
    else if(ql>mid) change(cur->rc,mid+1,r,ql,qr,val),insert(cur->lc);
    else change(cur->lc,l,mid,ql,qr,val),change(cur->rc,mid+1,r,ql,qr,val);
    push_up(cur);
}

int main() {
    scanf("%d%d",&n,&q);
    root=&x[++tot];
    for(int l,r,k,i=1; i<=q; i++) {
        scanf("%d%d%d",&l,&r,&k);
        if(k==2) k=0;
        change(root,1,n,l,r,k);
        printf("%d\n",n-root->sum);
    }
    
    return 0;
}

 

posted @ 2018-10-15 19:31  清风我已逝  阅读(182)  评论(0编辑  收藏  举报