Count the Colors(线段树,找颜色段条数)

本文介绍了一种通过构建线段树来解决颜色段计数问题的方法。该算法能够有效地统计不同颜色的可见线段数量,适用于处理大量线段数据的情况。文章提供了完整的代码实现,并附带了解题思路和关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Count the Colors

Time Limit: 2 Seconds      Memory Limit: 65536 KB

Painting some colored segments on a line, some previously painted segments may be covered by some the subsequent ones.

Your task is counting the segments of different colors you can see at last.

Input The first line of each data set contains exactly one integer n, 1 <= n <= 8000, equal to the number of colored segments.

Each of the following n lines consists of exactly 3 nonnegative integers separated by single spaces:
x1 x2 c
x1 and x2 indicate the left endpoint and right endpoint of the segment, c indicates the color of the segment.

All the numbers are in the range [0, 8000], and they are all integers.

Input may contain several data set, process to the end of file.

Output
Each line of the output should contain a color index that can be seen from the top, following the count of the segments of this color, they should be printed according to the color index.

If some color can't be seen, you shouldn't print it.

Print a blank line after every dataset.

Sample Input
5 0 4 4 0 3 1 3 4 2 0 2 2 0 2 3 4 0 1 1 3 4 1 1 3 2 1 3 1 6 0 1 0 1 2 1 2 3 1 1 2 0 2 3 0 1 2 1

Sample Output
1 1 2 1 3 1

1 1

0 2 1 1

题解:各种错。。。最终发现还是要插a+1,b才可以,因为是颜色段,并不是点,还有,那个n是n条线段,所以查找和建树均要是8000内建,否则会wa;

思路:-1代笔多色,0代表无色;

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int INF=0x3f3f3f3f;
#define mem(x,y) memset(x,y,sizeof(x))
#define SI(x) scanf("%d",&x)
#define PI(x) printf("%d",x)
#define SD(x,y) scanf("%lf%lf",&x,&y)
#define P_ printf(" ")
#define ll root<<1
#define rr root<<1|1
#define lson ll,l,mid
#define rson rr,mid+1,r
#define V(x) tree[x]
typedef long long LL;
const int MAXN=8010;
int color[MAXN];
int temp;
int tree[MAXN<<2];
void pushdown(int root){
	if(V(root)>0){
		V(ll)=V(root);
		V(rr)=V(root);
		V(root)=-1;
	}
}
void build(int root,int l,int r){
	int mid=(l+r)>>1;
	V(root)=0;
	if(l==r)return;
	build(lson);build(rson);
}
void update(int root,int l,int r,int A,int B,int v){
	if(l>=A&&r<=B){
		V(root)=v;
		return;
	}
	int mid=(l+r)>>1;
	pushdown(root);
	if(mid>=A)update(lson,A,B,v);
	if(mid<B)update(rson,A,B,v);
	V(root)=-1;
}
void query(int root,int l,int r){
	int mid=(l+r)>>1;
	if(temp==V(root))return;
	if(!V(root)){
		temp=0;return;
	}
	if(V(root)!=-1){
		if(temp!=V(root)){
			temp=V(root);
			color[temp]++;
			return;
		}
		return;
	}
	if(l==r)return;
		query(lson);
		query(rson);
}
int main(){
	int n;
	while(~scanf("%d",&n)){
		mem(color,0);
		build(1,1,8000);
		int a,b,c;
		int t=n;
		while(t--){
			scanf("%d%d%d",&a,&b,&c);
			update(1,1,8000,a+1,b,c+1);
		}
		query(1,1,8000);
		for(int i=1;i<=8001;i++){
			if(color[i])printf("%d %d\n",i-1,color[i]);
		}puts("");
	}
	return 0;
}

  

 

using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.Colors; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; using Autodesk.AutoCAD.Runtime; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; namespace ScaffoldPlugin { public class ScaffoldCommands { // 配置参 private static readonly double[] BarLengths = { 300, 600, 900, 1200, 1500, 1800 }; private static readonly string BlockDirectory = Path.Combine( Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), “ScaffoldBlocks”); // 容差参 private const double ToleranceValue = 0.1; // 几何计算容差 private const double SpacingTolerance = 150.0; // 横杆长度匹配容差 private const double MinAxisLength = 100.0; // 最小轴网线长度 private const double MinDistanceForBar = 50.0; // 最小横杆间距 private const double MaxGapFactor = 1.2; // 最大间隙因子 // 块名称定义 private const string PoleBlockName = "ScaffoldPole立杆"; private const string BarPrefix = "ScaffoldPole横杆"; // 图层定义 private const string PoleLayer = "盘扣-立杆"; private const string BarLayer = "盘扣-横杆"; private const string AxisLayer = "盘扣轴网"; private const string DebugLayer = "盘扣-调试"; // 调试用图层 // 主命令:布置脚手架 [CommandMethod("BuildPlatform", "BP", CommandFlags.Modal)] public void BuildPlatform() { Document doc = Application.DocumentManager.MdiActiveDocument; Database db = doc.Database; Editor ed = doc.Editor; try { // 检查块目录 if (!Directory.Exists(BlockDirectory)) { Directory.CreateDirectory(BlockDirectory); ShowErrorDialog($"块目录已创建: {BlockDirectory}\n请添加块文件后重新运行命令"); return; } // 创建所需图层 CreateLayerIfNotExists(db, PoleLayer, 7); // 红色 CreateLayerIfNotExists(db, BarLayer, 1); // 红色 CreateLayerIfNotExists(db, AxisLayer, 3); // 绿色 CreateLayerIfNotExists(db, DebugLayer, 2); // 黄色调试层 // 选择轴网线 var axisLineIds = SelectAxisLines(ed); if (axisLineIds == null || axisLineIds.Count == 0) { ShowErrorDialog("未选择轴网线或操作已取消!"); return; } // 获取轴网线对象 List<Line> axisLines = GetAxisLinesFromIds(db, axisLineIds); if (axisLines.Count == 0) { ShowErrorDialog("未到有效轴网线!"); return; } // 计算有效交点(只在线延伸相交处) ed.WriteMessage("\n正在计算有效交点..."); List<Point3d> validPoints = GetValidIntersectionPoints(axisLines); if (validPoints.Count == 0) { ShowErrorDialog("未到有效交点!"); return; } ed.WriteMessage($"\n到 {validPoints.Count} 个有效交点"); // 加载块定义 ed.WriteMessage("\n正在加载块定义..."); if (!LoadBlockDefinitions(db, ed)) return; // 清理现有脚手架 ed.WriteMessage("\n开始清理重叠区域的现有脚手架..."); CleanOverlappingScaffold(db, validPoints, ed); // 布置立杆(只在有效交点) ed.WriteMessage("\n开始布置立杆..."); int poleCount = PlacePoles(db, validPoints); ed.WriteMessage($"\n已布置 {poleCount} 根立杆"); // 布置横杆(只在连续线) ed.WriteMessage("\n开始布置横杆..."); int barCount = PlaceBars(db, validPoints, axisLines, ed); ed.WriteMessage($"\n已布置 {barCount} 根横杆"); // 结果反馈 if (poleCount == 0 && barCount == 0) { ShowErrorDialog("脚手架布置失败,未布置任何构件!"); } else { Application.ShowAlertDialog($"成功布置 {poleCount}根立杆和{barCount}根横杆!"); } } catch (System.Exception ex) { ShowErrorDialog($"发生错误: {ex.Message}\n详细请查看命令行日志"); ed.WriteMessage($"\n错误: {ex.Message}\n{ex.StackTrace}"); } } // 选择轴网线 private List<ObjectId> SelectAxisLines(Editor ed) { var lineIds = new List<ObjectId>(); var filter = new SelectionFilter(new[] { new TypedValue(0, "LINE"), new TypedValue(8, AxisLayer) }); var opts = new PromptSelectionOptions { MessageForAdding = "\n选择盘扣轴网线 (按Enter结束选择): ", MessageForRemoval = "\n移除不需要的轴网线: ", AllowDuplicates = false, RejectObjectsOnLockedLayers = true }; PromptSelectionResult selection = ed.GetSelection(opts, filter); if (selection.Status != PromptStatus.OK) { ed.WriteMessage("\n未选择任何轴网线或选择已取消"); return lineIds; } using (var trans = ed.Document.TransactionManager.StartTransaction()) { foreach (ObjectId id in selection.Value.GetObjectIds()) { if (id.ObjectClass.DxfName == "LINE") { Entity entity = trans.GetObject(id, OpenMode.ForRead) as Entity; if (entity != null && entity.Layer == AxisLayer) { if (entity is Line line && line.Length > MinAxisLength) { lineIds.Add(id); } } } } trans.Commit(); } ed.WriteMessage($"\n已选择 {lineIds.Count} 条有效轴网线"); return lineIds; } // 从ID获取轴网线对象 private List<Line> GetAxisLinesFromIds(Database db, List<ObjectId> lineIds) { List<Line> lines = new List<Line>(); using (Transaction tr = db.TransactionManager.StartTransaction()) { foreach (ObjectId id in lineIds) { Line line = tr.GetObject(id, OpenMode.ForRead) as Line; if (line != null && line.Length > MinAxisLength) { lines.Add(line.Clone() as Line); // 克隆以避免原始对象修改 } } tr.Commit(); } return lines; } // 计算有效交点 private List<Point3d> GetValidIntersectionPoints(List<Line> axisLines) { List<Point3d> validPoints = new List<Point3d>(); for (int i = 0; i < axisLines.Count; i++) { for (int j = i + 1; j < axisLines.Count; j++) { Line line1 = axisLines[i]; Line line2 = axisLines[j]; Point3dCollection intersections = new Point3dCollection(); line1.IntersectWith(line2, Intersect.ExtendBoth, intersections, IntPtr.Zero, IntPtr.Zero); foreach (Point3d pt in intersections) { if (IsValidIntersection(pt, line1, line2)) { validPoints.Add(pt); } } } } // 移除重复点 return validPoints.Distinct(new Point3dComparer(ToleranceValue)).ToList(); } // 点比较器(考虑容差) private class Point3dComparer : IEqualityComparer<Point3d> { private readonly double _tolerance; public Point3dComparer(double tolerance) { _tolerance = tolerance; } public bool Equals(Point3d p1, Point3d p2) { return p1.DistanceTo(p2) < _tolerance; } public int GetHashCode(Point3d p) { return p.X.GetHashCode() ^ p.Y.GetHashCode() ^ p.Z.GetHashCode(); } } // 检查是否为有效交点 private bool IsValidIntersection(Point3d pt, Line line1, Line line2) { return IsPointOnLineSegment(pt, line1, ToleranceValue) && IsPointOnLineSegment(pt, line2, ToleranceValue); } // 检查点是否在线范围内 private bool IsPointOnLineSegment(Point3d pt, Line line, double tolerance) { Vector3d lineVec = line.EndPoint - line.StartPoint; Vector3d startToPt = pt - line.StartPoint; double lineLengthSquared = lineVec.DotProduct(lineVec); double dotProduct = lineVec.DotProduct(startToPt); return dotProduct >= -tolerance && dotProduct <= lineLengthSquared + tolerance; } // 加载块定义 private bool LoadBlockDefinitions(Database db, Editor ed) { try { using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; // 加载立杆块 string polePath = Path.Combine(BlockDirectory, $"{PoleBlockName}.dwg"); if (!File.Exists(polePath)) { ShowErrorDialog($"立杆块文件未到: {polePath}"); return false; } if (!bt.Has(PoleBlockName)) { using (Database sourceDb = new Database(false, true)) { sourceDb.ReadDwgFile(polePath, FileOpenMode.OpenForReadAndAllShare, false, null); db.Insert(PoleBlockName, sourceDb, true); ed.WriteMessage($"\n已加载立杆块: {PoleBlockName}"); } } // 加载横杆块 foreach (double length in BarLengths) { string barName = $"{BarPrefix}{length}mm"; string barPath = Path.Combine(BlockDirectory, $"{barName}.dwg"); if (!bt.Has(barName)) { if (File.Exists(barPath)) { using (Database sourceDb = new Database(false, true)) { sourceDb.ReadDwgFile(barPath, FileOpenMode.OpenForReadAndAllShare, false, null); db.Insert(barName, sourceDb, true); } ed.WriteMessage($"\n已加载横杆块: {barName}"); } else { ed.WriteMessage($"\n警告:横杆块文件未到: {barPath}"); } } } tr.Commit(); } return true; } catch (System.Exception ex) { ShowErrorDialog($"加载块定义失败: {ex.Message}"); return false; } } // 清理现有脚手架 private void CleanOverlappingScaffold(Database db, List<Point3d> points, Editor ed) { if (points.Count == 0) return; // 计算包围盒 double minX = points.Min(p => p.X); double maxX = points.Max(p => p.X); double minY = points.Min(p => p.Y); double maxY = points.Max(p => p.Y); // 扩展边界 double padding = BarLengths.Max() * 1.5; Point3d minPt = new Point3d(minX - padding, minY - padding, 0); Point3d maxPt = new Point3d(maxX + padding, maxY + padding, 0); using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTableRecord btr = tr.GetObject( SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite) as BlockTableRecord; // 创建选择过滤器 TypedValue[] filterValues = { new TypedValue(0, "INSERT"), new TypedValue(8, $"{PoleLayer},{BarLayer}") }; SelectionFilter filter = new SelectionFilter(filterValues); // 创建选择区域 Point3dCollection pts = new Point3dCollection(); pts.Add(minPt); pts.Add(new Point3d(maxPt.X, minPt.Y, 0)); pts.Add(maxPt); pts.Add(new Point3d(minPt.X, maxPt.Y, 0)); // 选择区域内的块 PromptSelectionResult psr = ed.Document.Editor.SelectCrossingPolygon(pts, filter); if (psr.Status == PromptStatus.OK) { int count = 0; foreach (ObjectId id in psr.Value.GetObjectIds()) { Entity ent = tr.GetObject(id, OpenMode.ForWrite) as Entity; if (ent != null) { ent.Erase(); count++; } } ed.WriteMessage($"\n已清理 {count} 个现有脚手架构件"); } tr.Commit(); } } // 布置立杆 private int PlacePoles(Database db, List<Point3d> points) { int count = 0; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord btr = tr.GetObject( SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite) as BlockTableRecord; if (!bt.Has(PoleBlockName)) { Application.ShowAlertDialog($"错误:立杆块 {PoleBlockName} 未加载!"); return 0; } ObjectId poleBlockId = bt[PoleBlockName]; foreach (Point3d pt in points) { if (double.IsNaN(pt.X) || double.IsNaN(pt.Y)) continue; BlockReference br = new BlockReference(pt, poleBlockId); br.Layer = PoleLayer; btr.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); count++; } tr.Commit(); } return count; } // 布置横杆 private int PlaceBars(Database db, List<Point3d> validPoints, List<Line> axisLines, Editor ed) { int count = 0; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord btr = tr.GetObject( SymbolUtilityServices.GetBlockModelSpaceId(db), OpenMode.ForWrite) as BlockTableRecord; // 创建点空间索引 Point3dTree pointTree = new Point3dTree(validPoints, ToleranceValue * 10); // 处理所有轴网线 foreach (Line line in axisLines) { // 到线上所有有效交点 List<Point3d> linePoints = pointTree.GetPointsOnLine(line); if (linePoints.Count < 2) { continue; } // 按沿线的距离排序点 linePoints = linePoints.OrderBy(p => p.DistanceTo(line.StartPoint)).ToList(); // 将点分组为连续 List<List<Point3d>> segments = GroupPointsIntoSegments(linePoints, line, ed); // 在每个连续上布置横杆 foreach (var segment in segments) { if (segment.Count < 2) continue; for (int i = 0; i < segment.Count - 1; i++) { Point3d start = segment[i]; Point3d end = segment[i + 1]; double distance = start.DistanceTo(end); if (distance < MinDistanceForBar) continue; // 查最匹配的标准长度 double bestLength = FindBestBarLength(distance); if (bestLength < 0) continue; // 计算中点 Point3d midPoint = new Point3d( (start.X + end.X) / 2, (start.Y + end.Y) / 2, (start.Z + end.Z) / 2); // 计算旋转角度 Vector3d direction = end - start; double angle = direction.GetAngleTo(Vector3d.XAxis, Vector3d.ZAxis); // 处理角度象限问题 if (direction.Y < 0) angle = Math.PI * 2 - angle; // 生成块名 string blockName = $"{BarPrefix}{bestLength}mm"; if (!bt.Has(blockName)) { continue; } // 插入横杆 BlockReference br = new BlockReference(midPoint, bt[blockName]); br.Layer = BarLayer; br.Rotation = angle; btr.AppendEntity(br); tr.AddNewlyCreatedDBObject(br, true); count++; } } } tr.Commit(); } return count; } // 查最佳横杆长度 private double FindBestBarLength(double distance) { double bestLength = -1; double minDiff = double.MaxValue; foreach (double len in BarLengths) { double diff = Math.Abs(len - distance); if (diff < minDiff && diff <= SpacingTolerance) { minDiff = diff; bestLength = len; } } return bestLength; } // 将点分组为连续 private List<List<Point3d>> GroupPointsIntoSegments(List<Point3d> points, Line line, Editor ed) { List<List<Point3d>> segments = new List<List<Point3d>>(); if (points.Count < 2) return segments; List<Point3d> currentSegment = new List<Point3d> { points[0] }; double maxGap = BarLengths.Max() * MaxGapFactor; for (int i = 1; i < points.Count; i++) { double distance = points[i - 1].DistanceTo(points[i]); if (distance > maxGap) { if (currentSegment.Count > 1) { segments.Add(currentSegment); } currentSegment = new List<Point3d> { points[i] }; } else { currentSegment.Add(points[i]); } } if (currentSegment.Count > 1) { segments.Add(currentSegment); } return segments; } // 创建图层 private void CreateLayerIfNotExists(Database db, string layerName, short colorIndex) { using (Transaction tr = db.TransactionManager.StartTransaction()) { LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable; if (!lt.Has(layerName)) { lt.UpgradeOpen(); LayerTableRecord ltr = new LayerTableRecord { Name = layerName, Color = Color.FromColorIndex(ColorMethod.ByAci, colorIndex), IsPlottable = true }; lt.Add(ltr); tr.AddNewlyCreatedDBObject(ltr, true); } tr.Commit(); } } // 显示错误对话框 private void ShowErrorDialog(string message) { Application.ShowAlertDialog(message); } } // 空间索引树 public class Point3dTree { private readonly List<Point3d> points; private readonly double tolerance; public Point3dTree(List<Point3d> points, double tolerance) { this.points = points; this.tolerance = tolerance; } public List<Point3d> GetPointsOnLine(Line line) { List<Point3d> result = new List<Point3d>(); // 计算线包围盒 Point3d min = new Point3d( Math.Min(line.StartPoint.X, line.EndPoint.X) - tolerance, Math.Min(line.StartPoint.Y, line.EndPoint.Y) - tolerance, 0); Point3d max = new Point3d( Math.Max(line.StartPoint.X, line.EndPoint.X) + tolerance, Math.Max(line.StartPoint.Y, line.EndPoint.Y) + tolerance, 0); // 快速筛选候选点 foreach (Point3d pt in points) { if (pt.X >= min.X && pt.X <= max.X && pt.Y >= min.Y && pt.Y <= max.Y) { if (IsPointOnLineSegment(pt, line, tolerance)) { result.Add(pt); } } } return result; } // 检查点是否在线范围内 private bool IsPointOnLineSegment(Point3d pt, Line line, double tolerance) { Vector3d lineVec = line.EndPoint - line.StartPoint; Vector3d startToPt = pt - line.StartPoint; double lineLengthSquared = lineVec.DotProduct(lineVec); double dotProduct = lineVec.DotProduct(startToPt); return dotProduct >= -tolerance && dotProduct <= lineLengthSquared + tolerance; } } } 网格斜线的杆件布置不在斜线上 根据问题重新编写完整代码
07-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值