線段樹專題—ZOJ1610 Count the Colors
阿新 • • 發佈:2018-03-28
col pan ace ons cst class map led return
題意:給一個n,代表n次操作,接下來每次操作表示把[l。r]區間的線段塗成k的顏色當中,l,r,k的範圍都是0到8000
分析:事實上就是拿線段樹維護一段區間的顏色,整體用到的是線段樹的區間更新把,可是會給人一種區間合並的錯覺
註意:這題比較坑的是千萬不能拿n建樹,不然就會segmentation fault,必須拿8000建樹。也就是樹是固定的
代碼:
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<map> #include<set> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; const int maxn = 1e4+5; int col[maxn<<2]; int num[maxn]; int ncol; void down(int l,int r,int rt){ if(col[rt]!=-1){ col[rt<<1]=col[rt<<1|1]=col[rt]; col[rt]=-1; } } void update(int L,int R,int k,int l,int r,int rt){ if(L<=l&&r<=R){ col[rt]=k; return; } down(l,r,rt); int mid=(l+r)>>1; if(L<=mid) update(L,R,k,l,mid,rt<<1); if(R>mid) update(L,R,k,mid+1,r,rt<<1|1); } void query(int l,int r,int rt){ if(l==r){ if(col[rt]>=0&&col[rt]!=ncol) num[col[rt]]++; //統計連續顏色段的個數 ncol=col[rt]; return; } down(l,r,rt); int mid=(l+r)>>1; query(l,mid,rt<<1); query(mid+1,r,rt<<1|1); } int main() { int n; while(scanf("%d",&n)!=-1){ ncol=-1; memset(num,0,sizeof(num)); memset(col,-1,sizeof(col)); //建樹 for(int i=1;i<=n;i++){ int c,l,r; scanf("%d%d%d",&l,&r,&c); if(l<r) update(l+1,r,c,1,8000,1); } query(1,8000,1); for(int i=0;i<=8000;i++){ if(num[i]) printf("%d %d\n",i,num[i]); } printf("\n"); } }
線段樹專題—ZOJ1610 Count the Colors