COGS 775. 山海经 【线段树】

                                                           775. 山海经

 

【问题描述】

“南山之首日鹊山。其首日招摇之山,临于西海之上,多桂,多金玉。有草焉,其状如韭而青华,其名日祝余,食之不饥……又东三百里,日堂庭之山,多棪木,多白猿,多水玉,多黄金。

又东三百八十里,日猨翼之山,其中多怪兽,水多怪鱼,多白玉,多蝮虫,多怪蛇,名怪木,不可以上。……”

《山海经》是以山为纲,以海为线记载古代的河流、植物、动物及矿产等情况,而且每一条记录路线都不会有重复的山出现。某天,你的地理老师想重游《山海经》中的路线,为了简化问题,老师已经把每座山用一个整数表示他对该山的喜恶程度,他想知道第a座山到第b座山的中间某段路(i,j)。能使他感到最满意,即(i,j)这条路上所有山的喜恶度之和是(c,d)(a≤c≤d≤b)最大值。于是老师便向你请教,你能帮助他吗?值得注意的是,在《山海经》中,第i座山只能到达第i+1座山。

 

【输入】

输入第1行是两个数,n,m,2≤n≤100000,1≤m≤100000,n表示一共有n座山,m表示老师想查询的数目。

第2行是n个整数,代表n座山的喜恶度,绝对值均小于10000。

以下m行每行有a,b两个数,1≤a≤j≤b≤m,表示第a座山到第b座山。

 

【输出】

一共有m行,每行有3个数i,j,s,表示从第i座山到第j座山总的喜恶度为s。显然,对于每个查询,有a≤i≤j≤b,如果有多组解,则输出i最小的,如果i也相等,则输出j最小的解。

 

【输入样例】

5 3

5 -6 3 -1 4

1 3

1 5

5 5

【输出样例】

1 1 5

3 5 6

5 5 4

 

我感觉炒鸡恶心 啊 

线段树维护十个域 

常规 的 l r 代表此区间左右端点

ql qr 代表此区间连续子段最大的区间的左右端点

lr 代表从左端点 最大左子串能到达的位置

rl 代表从右端点 最大右子串能到达的位置

lm rm代表最大左子串和最大右子串

sum 代表区间和 

mx代表区间最大连续子串

 

建树更新,查询也要更新

 

  1 #include <cstdio>
  2 #include <cctype>
  3 
  4 const int MAXN=100010;
  5 
  6 int n,m;
  7 
  8 struct SegmentTree {
  9     int l,r;
 10     int ql,qr,lr,rl;
 11     int sum,lm,rm,mx;
 12 };
 13 SegmentTree t[MAXN<<2];
 14 
 15 inline void read(int&x) {
 16     int f=1;register char c=getchar();
 17     for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar());
 18     for(;isdigit(c);x=x*10+c-48,c=getchar());
 19     x=x*f;
 20 }
 21 
 22 inline int max(int a,int b) {return a<b?b:a;}
 23 
 24 inline void up(int now) {
 25     t[now].sum=t[now<<1].sum+t[now<<1|1].sum;
 26     
 27     t[now].lm=t[now<<1].lm;
 28     t[now].lr=t[now<<1].lr;
 29     if(t[now].lm<t[now<<1].sum+t[now<<1|1].lm) {
 30         t[now].lm=t[now<<1].sum+t[now<<1|1].lm;
 31         t[now].lr=t[now<<1|1].lr;
 32     }
 33     
 34     t[now].rm=t[now<<1|1].rm;
 35     t[now].rl=t[now<<1|1].rl;
 36     if(t[now].rm<=t[now<<1|1].sum+t[now<<1].rm) {
 37         t[now].rm=t[now<<1|1].sum+t[now<<1].rm;
 38         t[now].rl=t[now<<1].rl;
 39     }
 40     
 41     t[now].mx=t[now<<1].mx;
 42     t[now].ql=t[now<<1].ql;t[now].qr=t[now<<1].qr;
 43     if(t[now].mx<t[now<<1].rm+t[now<<1|1].lm) {
 44         t[now].mx=t[now<<1].rm+t[now<<1|1].lm;
 45         t[now].ql=t[now<<1].rl;
 46         t[now].qr=t[now<<1|1].lr;
 47     }
 48     if(t[now].mx<t[now<<1|1].mx){
 49         t[now].mx=t[now<<1|1].mx;
 50         t[now].ql=t[now<<1|1].ql;
 51         t[now].qr=t[now<<1|1].qr;
 52     }
 53     return;
 54 }
 55 
 56 void build_tree(int now,int l,int r) {
 57     t[now].l=l,t[now].r=r;
 58     if(l==r) {
 59         read(t[now].sum);
 60         t[now].ql=t[now].qr=l;
 61         t[now].lr=t[now].rl=l;
 62         t[now].mx=t[now].lm=t[now].rm=t[now].sum;
 63         return;
 64     }
 65     int mid=(l+r)>>1;
 66     build_tree(now<<1,l,mid);
 67     build_tree(now<<1|1,mid+1,r);
 68     up(now);
 69 }
 70 
 71 SegmentTree query(int now,int l,int r) {
 72     if(l==t[now].l&&r==t[now].r) return t[now];
 73     int mid=(t[now].l+t[now].r)>>1;
 74     SegmentTree ls,rs,ans;
 75     if(r<=mid) return query(now<<1,l,r);
 76     else if(l>mid) return query(now<<1|1,l,r);
 77     else {
 78         ls=query(now<<1,l,mid);
 79         rs=query(now<<1|1,mid+1,r);
 80         ans.l=ls.l;ans.r=rs.r;
 81         
 82         ans.lm=ls.lm;ans.lr=ls.lr;
 83         if(ans.lm<ls.sum+rs.lm) {
 84             ans.lm=ls.sum+rs.lm;
 85             ans.lr=rs.lr;
 86         }
 87         
 88         ans.rm=rs.rm;ans.rl=rs.rl;
 89         if(ans.rm<rs.sum+ls.rm) {
 90             ans.rm=rs.sum+ls.rm;
 91             ans.rl=ls.rl;
 92         }
 93         
 94         ans.sum=ls.sum+rs.sum;
 95         ans.mx=ls.mx,ans.ql=ls.ql,ans.qr=ls.qr;
 96         if(ls.rm+rs.lm>ans.mx) {
 97             ans.mx=ls.rm+rs.lm;
 98             ans.ql=ls.rl;ans.qr=rs.lr;
 99         }
100         if(rs.mx>ans.mx) {
101             ans.mx=rs.mx;
102             ans.ql=rs.ql;ans.qr=rs.qr;
103         }
104     }
105     return ans;
106 }
107 
108 int hh() {
109     freopen("hill.in","r",stdin);
110     freopen("hill.out","w",stdout);
111     read(n);read(m);
112     build_tree(1,1,n);
113     for(int x,y;m--;) {
114         read(x);read(y);
115         SegmentTree now=query(1,x,y);
116         printf("%d %d %d\n",now.ql,now.qr,now.mx);
117     }
118     return 0;
119 }
120 
121 int sb=hh();
122 int main(int argc,char**argv) {;}
代码

 

以下是将代码修改为cot平滑的方法: 1. 首先,需要使用边界角的cot权重计算每个顶点的权重。 2. 然后,使用cot权重对每个顶点的邻域点进行加权计算,得到平滑后的坐标。 3. 最后,根据平滑后的坐标更新每个顶点的位置。 修改后的代码如下: float smooth() { float err = -1; cogs.clear(); v_end = mesh.vertices_end(); //cot平滑 for (v_it = mesh.vertices_begin(); v_it != v_end; ++v_it) { cog[0] = cog[1] = cog[2] = weight_sum = 0.0; for (vv_it = mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it) { double cot_weight = 0.0; MyMesh::HalfedgeHandle heh = mesh.find_halfedge(*v_it, *vv_it); if (!mesh.is_boundary(heh)) { MyMesh::HalfedgeHandle prev_heh = mesh.prev_halfedge_handle(heh); MyMesh::HalfedgeHandle next_heh = mesh.next_halfedge_handle(heh); MyMesh::VertexHandle prev_vh = mesh.to_vertex_handle(prev_heh); MyMesh::VertexHandle next_vh = mesh.to_vertex_handle(next_heh); MyMesh::Point prev_p = mesh.point(prev_vh); MyMesh::Point curr_p = mesh.point(*v_it); MyMesh::Point next_p = mesh.point(next_vh); double cot_alpha = cot(prev_p - curr_p, next_p - curr_p); double cot_beta = cot(curr_p - prev_p, next_p - prev_p); cot_weight = cot_alpha + cot_beta; } cog += cot_weight * mesh.point(*vv_it); weight_sum += cot_weight; } cogs.push_back(cog / weight_sum); } for (v_it = mesh.vertices_begin(), cog_it = cogs.begin(); v_it != v_end; ++v_it, ++cog_it) { if (!mesh.is_boundary(*v_it)) { MyMesh::Point p = mesh.point(*v_it); err = max(err, (p - *cog_it).norm()); mesh.set_point(*v_it, *cog_it); } } return err; } 其cot函数的定义如下: double cot(MyMesh::Point a, MyMesh::Point b) { return dot(a, b) / cross(a, b).norm(); } 注意,这里使用的是边界角的cot权重,因此在计算cot权重时需要判断当前边是否为边界。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值