Count the Colors(线段树,区间修改,单点查询)

    科技2025-02-26  3

    题目传送门

    Count the Colors

    题目大意

    一面长为8000的墙,给出n次操作,每次给出x,y,z,代表在x~y区间将墙粉刷成颜色z,后面的粉刷可以覆盖之前的 求最后墙上不同的颜色的种数和每种颜色非连续的段数

    思路

    很明显的区间修改,单点查询 注意点: 多组输入 最后换行,不然会PE 显然区间是左开右闭的 编号从0开始代表颜色可以为0

    AC Code

    #include<bits/stdc++.h> using namespace std; #define debug(a) cout<<#a<<"="<<a<<endl; const int N=8009; int n, l, r, c; int ans[N], colour[N], idx; struct segtree{ int l, r; int colour; }tr[N<<2]; inline int read() { int ans=0; char last=' ',ch=getchar(); while(ch<'0'||ch>'9') last=ch,ch=getchar(); while(ch>='0'&&ch<='9') ans=ans*10+ch-'0',ch=getchar(); if(last=='-') ans=-ans; return ans; } inline int lc(int p) {return p<<1;} inline int rc(int p) {return p<<1|1;} inline void build(int p, int l, int r){ tr[p].l=l, tr[p].r=r; tr[p].colour=-1; if(l==r) return ; int mid=(l+r)>>1; build(lc(p), l, mid); build(rc(p), mid+1, r); } inline void f(int p, int k){ tr[p].colour=k; } inline void push_down(int p){ f(lc(p), tr[p].colour); f(rc(p), tr[p].colour); tr[p].colour=-1; } inline void updata(int p, int l, int r, int x, int y, int k){ if(x>r || y<l) return ; if(l<=x && y<=r){ tr[p].colour=k; return ; } if(tr[p].colour!=-1) push_down(p); int mid=(x+y)>>1; updata(lc(p), l, r, x, mid, k); updata(rc(p), l, r, mid+1, y, k); } inline void query(int p, int x, int y){ if(x==y){ colour[idx++]=tr[p].colour; return ; } int mid=(x+y)>>1; if(tr[p].colour!=-1) push_down(p); query(lc(p), x, mid); query(rc(p), mid+1, y); } int main(){ while(~scanf("%d", &n)){ build(1,0,8000); idx=0; memset(colour, -1, sizeof(colour)); memset(ans, 0, sizeof(ans)); for(int i=1; i<=n; i++){ l=read(); r=read(); c=read(); updata(1,l,r-1,0,8000,c); } query(1,0,8000); for(int i=0; i<idx; i++){ if(colour[i]!=colour[i+1] && colour[i]!=-1){ ans[colour[i]]++; } } for(int i=0; i<=8000; i++) if(ans[i]) cout<<i<<" "<<ans[i]<<endl; cout<<endl; } return 0; }
    Processed: 0.012, SQL: 8