F - Count the Colors
思路:调了一个小时,但是发现自己线段树木有写错,颜色统计出了错误。但是不明白自己颜色统计为什么错了。
求大佬指点迷津。思路很简单,就是一个裸的线段树。只要推出样例就做出来了。
以下是两种颜色统计:
这是我的错误的:
for(int i=1;i<=8009;i++){ if(vis[i]!=vis[i-1]&&vis[i-1]!=-1) ans[vis[i-1]]++; if(i==8000&&vis[i]!=-1) ans[vis[i-1]]++; }
后来大佬解决了疑惑,改成酱就对了:
for(int i=1;i<=8009;i++) if(vis[i]!=vis[i-1]&&vis[i-1]!=-1) ans[vis[i-1]]++;
是因为本来i就超过了最大范围,所以最后一个一定会被统计上,再加上特判就会造成重复计数。
这是正确的:
int i=1; while(i<MAXN){ int flagor=vis[i],j=i+1; if(flagor==-1){ ++i;continue; } while(vis[j]!=-1&&vis[j]==flagor&&j<MAXN) ++j; ++ans[flagor];i=j; }
cpp:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 8010 using namespace std; int n,m; struct nond{ int l,r,flag; }tree[MAXN*4]; int vis[MAXN*4],ans[MAXN*4]; void build(int now,int l,int r){ tree[now].l=l;tree[now].r=r;tree[now].flag=-1; if(tree[now].l==tree[now].r) return ; int mid=(tree[now].l+tree[now].r)/2; build(now*2,l,mid); build(now*2+1,mid+1,r); } void down(int now){ tree[now*2].flag=tree[now].flag; tree[now*2+1].flag=tree[now].flag; tree[now].flag=-1; return ; } void change(int now,int l,int r,int k){ if(tree[now].l==l&&tree[now].r==r){ tree[now].flag=k; return ; } if(tree[now].flag==k) return ; if(tree[now].flag!=-1) down(now); int mid=(tree[now].l+tree[now].r)/2; if(r<=mid) change(now*2,l,r,k); else if(l>mid) change(now*2+1,l,r,k); else{ change(now*2,l,mid,k);change(now*2+1,mid+1,r,k); } } void query(int now){ if(tree[now].flag!=-1){ for(int i=tree[now].l;i<=tree[now].r;i++) vis[i]=tree[now].flag; return ; } if(tree[now].l==tree[now].r) return ; query(now*2); query(now*2+1); } int main(){ while(scanf("%d",&n)!=EOF){ memset(ans,0,sizeof(ans)); memset(vis,-1,sizeof(vis)); build(1,1,8000); for(int i=1;i<=n;i++){ int x,y,z; scanf("%d%d%d",&x,&y,&z); change(1,x+1,y,z); } query(1); for(int i=1;i<=8009;i++) if(vis[i]!=vis[i-1]&&vis[i-1]!=-1) ans[vis[i-1]]++; for(int i=0;i<=8009;i++) if(ans[i]) printf("%d %d\n",i,ans[i]); cout<<endl; } }
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。