1610
题目 点击打开链接
用线段树的方法, 不明白的是到底设树的结点的数量是多少比较合适?线段的两倍是不够的,我设了三倍,还有计算颜色那里,我没有用老师的方法,而是自己想的方法,怎么办??真是觉得自己越来越聪明了
过程其实很蠢,老是想当然,不过也锻炼了我一下要怎么调试,以后像这种有树呀,有图的题一定要想画一下草稿,不然过程真的很痛苦,如果先画了一下草稿,思路也会清晰很多,或者用小一点的树调试一下,看看一个完整的过程,真的会好很多。不要自以为是,想着大概是这样,这真是自讨苦吃!
//#include "stdafx.h" #include <iostream> #include "stdio.h" #include <math.h> using namespace std; const int MAX = 8005; int color[8000][2]; struct Node { int ld, rd; int key; } Tree[MAX * 3]; void buildtree(int i,int a,int b)//建立一棵空线段树 i 为数组下标 ,a到b 为长度 { Tree[i].ld = a; Tree[i].rd = b; Tree[i].key = -1;//初始化为-1,表示没有颜色 if (b - a == 1) return; buildtree(i * 2, a, (a + b) / 2);//建子树 buildtree(i * 2 + 1, (a + b) / 2, b); return; } void insert(int i, int a, int b, int key) { if (Tree[i].key == key)//颜色一样,不需要往下进行 return; if (a<=Tree[i].ld&&Tree[i].rd<=b)//完全覆盖某一结点 { Tree[i].key = key; return; } if(Tree[i].key != -2)//有颜色才下分,不然会将颜色清掉! { Tree[2 * i].key = Tree[i].key;//颜色下分到下一层 Tree[2 * i + 1].key = Tree[i].key;//颜色下分到下一层 } Tree[i].key = -2;//标志向下颜色有不同,下层有颜色,//分完再赋值为-2.。。真是蠢爆了!!T_T if (a < (Tree[i].ld + Tree[i].rd) / 2) insert(i * 2, a, b, key); if (b>(Tree[i].ld + Tree[i].rd) / 2) insert(i * 2+1, a, b, key); } /////计算颜色,老师好像说了用数组的方法,不过我这个好像简单一点吧?
//因为在树里面递归时,线段也是连续的 画一下图就明白 了 void dfs(int i) { if (Tree[i].key == -1)//没有颜色 ,可以不用再向下进行了 return; if (Tree[i].key==-2)//下层有不同的颜色 { dfs(i * 2); dfs(i * 2 + 1); return; } if (color[Tree[i].key][1] != Tree[i].ld)//不相连加1 color[Tree[i].key][0]++;//线段加一 color[Tree[i].key][1] = Tree[i].rd;//记住它的右坐标,下次如果相连,则不加1 } int main() { int n; int a, b, c; while (~scanf("%d", &n))//新学到:) { buildtree(1, 0, 8000);//注意是1开始 //memset(color, 0, sizeof(color)); for (int k = 0; k < 8000;k++) { color[k][0] = 0; color[k][1] = -1;//初始上一个线段的右边是-1,不然会少算。。。一开始弄成0了。。 } while (n--) { cin >> a >> b >> c; insert(1,a, b, c); } dfs(1); for (int i = 0; i < 8000; i++) { if (color[i][0]) cout << i << " " << color[i][0] << endl; } cout << endl; } }