19 上海網絡賽 B. Light bulbs (線段樹動態開點 卡過去)或者(差分 正解)

傳送門

題意:N個燈泡,m次操作,每次選定一個區間,將這些燈泡的狀態反轉,求最後亮着的燈泡的數量。

思路: 差分,線段樹 ,分塊應該都可以,但這題卡時間,卡內存,差分是正解。

區間反轉奇數次的才需要統計,偶數次的不需要 , 例如 ;(1,6)(4,8)只需統計(1,3)和(7,8)

 

差分 正解

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <math.h>
#define mems(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int N=1e5+5;

struct node
{
    int a,b;
}s[2010];
bool cmp(node x,node y)
{
    return x.a<y.a;
}
int main()
{
    int t,p=1 ;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        int cnt=0;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            s[++cnt].a=l;
            s[cnt].b=1;
            s[++cnt].a=r+1;
            s[cnt].b=-1;
        }
        sort(s+1,s+cnt+1,cmp);
        int sum=0;int ans=0;
        for(int i=1;i<=cnt;i++)
        {
            sum+=s[i].b;
            if(sum&1)
                ans+=s[i+1].a-s[i].a;
        }
        printf("Case #%d: %d\n",p++,ans);
    }
}

線段樹 動態開點 卡時間過去的

#include <cstdio>
#include <queue>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <map>
#include <iterator>
#include <vector>
#include <set>
#include <bitset>
#include <stack>
#define ull unsigned long long
#define Mod(x) (x+mod)%mod
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define mems(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long ll;
const int N=1e5+5;
const double pi=acos(-1);
const int inf=0x3f3f3f3f;
inline int read(){
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}
int id;
struct node
{
    int sum,l,r,lazy;
}se[N];
inline int build()
{
    ++id;
    se[id].l=se[id].r=se[id].sum=0;
    se[id].lazy=0;
    return id;
}
void pushdown(int l,int r,int rt)
{
    if(se[rt].lazy==0) return;
    int mid=(l+r)>>1;
    if(l!=r)
    {
        if(se[rt].l==0) se[rt].l=build();
        if(se[rt].r==0) se[rt].r=build();
        se[se[rt].l].sum=(mid-l+1)-se[se[rt].l].sum;
        se[se[rt].r].sum=(r-mid)-se[se[rt].r].sum;
        se[se[rt].l].lazy^=1;
        se[se[rt].r].lazy^=1;
    }
    se[rt].lazy=0;
}
void update(int l,int r,int L,int R,int rt)
{
    if(L<=l&&r<=R)
    {
        se[rt].lazy^=1;
        se[rt].sum=(r-l+1)-se[rt].sum;
        return ;
    }
    pushdown(l,r,rt);
    int mid=(l+r)>>1;
    if(L<=mid)
    {
        if(se[rt].l==0)
            se[rt].l=build();
        update(l,mid,L,R,se[rt].l);
    }
    if(R>mid)
    {
        if(se[rt].r==0)
            se[rt].r=build();
        update(mid+1,r,L,R,se[rt].r);
    }
    se[rt].sum=se[se[rt].l].sum+se[se[rt].r].sum;
}

int main()
{
    int u,p=1;
    u=read();
    while(u--)
    {
        int n,m;
        n=read();m=read();
        id=0;
        build();
        for(int i=1;i<=m;i++)
        {
            int l,r;
            l=read();r=read();
            l++;r++;
            update(1,n,l,r,1);
        }
        printf("Case #%d: %d\n",p++,se[1].sum);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章