HLD (Heavy-Light Decomposition)
是一种用于处理树上路径问题的算法。它将树分解成一些“重链”和“轻链”,使得在这些链上进行操作变得高效。以下是 HLD 算法的详细讲解:
背景
在树上进行某些操作时(如路径查询、更新等),直接处理可能会导致复杂度较高。HLD 通过将树划分为多个链来简化这些操作,从而使得某些问题可以在更低的复杂度下解决。HLD 常与 LCA (Lowest Common Ancestor) 算法结合使用,以高效地处理路径查询和更新操作。
HLD 的主要步骤
-
树的分解
- 选择重链与轻链:
- 对于树的每个节点,计算其子树的大小(
subtree size
)。 - 将每个节点的子节点按子树大小排序,选择最大的子树作为“重链”。
- 除了重链之外的子树称为“轻链”。
- 对于树的每个节点,计算其子树的大小(
- 链的分组:
- 以重链为主,形成一系列链,每个链由多个节点组成。
- 每个节点属于某一条链,通过链接链的根节点(称为链的“顶部”)来管理。
- 选择重链与轻链:
-
数据结构和数组
- 链顶:每个节点的链顶节点,用于表示该节点所在链的起始节点。
- 深度:节点的深度。
- 子树大小:节点子树的节点数量。
- 时间戳(Euler Tour):通过 DFS 遍历树,将树展平成线性序列。
-
主要操作
-
路径查询:
- 使用链顶来快速定位路径上的节点。
- 将路径分解为多个链上的子路径,使用链顶的管理来简化处理。
-
路径更新:
- 类似于路径查询,将更新操作分解到多个链上。
-
-
常用函数
lca(u, v)
:计算节点u
和v
的最低公共祖先。HLD 和 LCA 算法通常结合使用来高效地解决这个问题。isAncester(u, v)
:检查节点u
是否是节点v
的祖先。jump(u, k)
:从节点u
向上跳k
步,返回跳转后的节点。
示例代码解释
以下是 HLD 算法的简化示例代码:
struct HLD {
int n;
std::vector<int> siz, top, dep, parent, in, out, seq;
std::vector<std::vector<int>> adj;
int cur;
HLD(int n) {
init(n);
}
void init(int n) {
this->n = n;
siz.resize(n);
top.resize(n);
dep.resize(n);
parent.resize(n);
in.resize(n);
out.resize(n);
seq.resize(n);
cur = 0;
adj.assign(n, {});
}
void addEdge(int u, int v) {
adj[u].push_back(v);
adj[v].push_back(u);
}
void work(int root = 0) {
top[root] = root;
dep[root] = 0;
parent[root] = -1;
dfs1(root);
dfs2(root);
}
void dfs1(int u) {
if (parent[u] != -1) {
adj[u].erase(std::find(adj[u].begin(), adj[u].end(), parent[u]));
}
siz[u] = 1;
for (auto &v : adj[u]) {
parent[v] = u;
dep[v] = dep[u] + 1;
dfs1(v);
siz[u] += siz[v];
if (siz[v] > siz[adj[u][0]]) {
std::swap(v, adj[u][0]);
}
}
}
void dfs2(int u) {
in[u] = cur++;
seq[in[u]] = u;
for (auto v : adj[u]) {
top[v] = v == adj[u][0] ? top[u] : v;
dfs2(v);
}
out[u] = cur;
}
int lca(int u, int v) {
while (top[u] != top[v]) {
if (dep[top[u]] > dep[top[v]]) {
u = parent[top[u]];
} else {
v = parent[top[v]];
}
}
return dep[u] < dep[v] ? u : v;
}
};
代码解释
-
初始化:
init(int n)
:初始化 HLD 数据结构。
-
添加边:
addEdge(int u, int v)
:将树的边加入到邻接表中。
-
处理链:
work(int root)
:执行 HLD 算法,分解树并计算链顶和相关数据。
-
DFS 遍历:
dfs1(int u)
:计算每个子树的大小,并选择重链。dfs2(int u)
:为每个节点分配时间戳和链顶信息。
-
计算 LCA:
lca(int u, int v)
:计算节点u
和v
的最低公共祖先。
通过这种分解方法,HLD 可以将路径问题转化为处理链上的问题,使得操作变得高效。这种方法适合在树形结构上进行频繁的路径查询和更新操作。
树状数组
维护前缀和和区间修改
1。从父节点走到子节点,寻找x若干个0,
2.通过子节点找父节点
找到所有包含x的子节点,怎么找,
找到的是直接包含的区间,唯一的直接影响的区间,树
p = x + lowbit(x), 从下往上迭代的过程,
直接前驱:查询前缀和
int sum(int i){
int s = 0;
for(; i > 0; i -= lowbit(i)
s += c[i];
return s;
}
点更新
void add(int i, int z){
for(; i <= n; i += lowbit(i) // 直接猴急, 父节点 i+ lowbit(i)
c[i] += z;
}
查询区间和:
int sum(int i, int j){
return sum(j) - sum(i - 1);
}
建树,因为tr[i]指的区间是[x-lowbit(x)+ 1,x]而不是前缀和,所以不应该跳到之前的位数上
比如c[3]= a[3]而不是c[3] = a[3] + c[2];
for(int x = 1;x <= n;x ++)
for(int i = x - 1;i >= x - lowbit(x) + 1;i -= lowbit(i))
tr[x] += tr[i];
第0层
前缀查询需要O(logn), 区间求和O(logn), 点更新O(logn), 点查询O(logn), 区间修改O(nlogn)
当问题满足减法规则时,sum(i,j) = sum[j] - sum[j - 1]当问题不满足减肥规则hi,比如求区间a(i j)最大值,则需要要用线段树来求解。
分为区修和点修,区修需要利用差分,再求出某一个数的值
P3374 【模板】树状数组 1
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
map<pair<int, int>, int> q;
set<pair<int, int>> res;
#define fi first
#define se second
int n, m;
vector<int> s;
int lowbit(int i){return i & -i;}
void add(int i, int k){ for(; i <= n; i += lowbit(i)) s[i] += k; }
int sum(int i) {int r = 0; for(; i > 0; i -= lowbit(i)) r += s[i]; return r;}
int sumall(int i, int j){return sum(j) - sum(i - 1);}
void solve() {
cin >> n >> m;
s.resize(n + 1);
for(int i = 1; i <= n; i ++){ int x; cin >> x; add(i, x);}
for(int i = 1; i <= m; i ++){
int x, a, b;
cin >> x >> a >> b;
if(x == 1) add(a, b);
else cout << sumall(a, b) << endl;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
solve();
return 0;
}
o(n)时间建立树状数组
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define fi first
#define se second
int n, m;
vector<int> s, a;
int lowbit(int i) {
return i & -i;
}
void add(int i, int k) {
for (; i <= n; i += lowbit(i))
s[i] += k;
}
int sum(int i) {
int r = 0;
for (; i > 0; i -= lowbit(i))
r += s[i];
return r;
}
int sumall(int i, int j) {
return sum(j) - sum(i - 1);
}
void buildBIT(const vector<int>& pre) {
for (int i = 1; i <= n; i++) {
s[i] = pre[i] - pre[i - lowbit(i)];
}
}
void solve() {
cin >> n >> m;
s.resize(n + 1, 0); // Initialize with zeros
a.resize(n + 1);
vector<int> prefix(n + 1, 0);
for (int i = 1; i <= n; i++) {
cin >> a[i];
prefix[i] = prefix[i - 1] + a[i];
}
// Build the BIT using prefix sums
buildBIT(prefix);
for (int i = 0; i < m; i++) {
int x, a, b;
cin >> x >> a >> b;
if (x == 1)
add(a, b); // Update the tree with value b at index a
else
cout << sumall(a, b) << endl; // Query the sum from index a to b
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
solve();
return 0;
}
P3368 【模板】树状数组 2
利用差分求某个数的值, m*logn
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
map<pair<int, int>, int> q;
set<pair<int, int>> res;
#define fi first
#define se second
int n, m;
vector<int> s, t;
int lowbit(int i){return i & -i;}
void add(int i, int k){ for(; i <= n; i += lowbit(i)) s[i] += k; }
int sum(int i) {int r = 0; for(; i > 0; i -= lowbit(i)) r += s[i]; return r;}
int sumall(int i, int j){return sum(j) - sum(i - 1);}
void solve() {
cin >> n >> m;
s.resize(n + 1, 0);
t.resize(n + 1, 0);
for(int i = 1; i <= n; i ++){ cin >> t[i];}
for(int i = 1; i <= m; i ++){
int x;
cin >> x;
if(x == 1) {int a, b, c; cin >> a >> b >> c; add(a, c), add(b + 1, -c);}
else {int a; cin >> a; cout << t[a] + sum(a) << endl;}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
solve();
return 0;
}
POJ 数星星
给定升序的点
241. 楼兰图腾
统计每个子集的方案数。统计出左边的数量和右边的数量相乘。相当于统计一个区间的和,从左到右,和从右到左,统计对于大于或小于k的数。
由于a[i]是1-n的排列,所以我们完全可以进行对x的数量进行求和,所以才能用树状数组。
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
map<pair<int, int>, int> q;
set<pair<int, int>> res;
typedef long long ll;
#define fi first
#define se second
int n;
vector<int> s, a;
vector<int> Greater, lower;
int lowbit(int i){return i & -i;}
void add(int i, int k){ for(; i <= n; i += lowbit(i)) s[i] += k; }
int sum(int i) {int r = 0; for(; i > 0; i -= lowbit(i)) r += s[i]; return r;}
int sumall(int i, int j){return sum(j) - sum(i - 1);}
void solve() {
cin >> n;
s.resize(n + 1);
a.resize(n + 1);
Greater.resize(n + 1);
lower.resize(n + 1);
for(int i = 1; i <= n; i ++){ cin >> a[i];}
for(int i = 1; i <= n; i ++){
int y = a[i];
Greater[i] = sum(n) - sum(y);
lower[i] = sum(y - 1);
add(y, 1);
}
fill(s.begin(), s.end(), 0);
ll res1 = 0, res2 = 0;
for (int i = n; i; i --)
{
int y = a[i];
res1 += Greater[i] * (ll)(sum(n) - sum(y));
res2 += lower[i] * (ll)(sum(y - 1));
add(y, 1);
}
cout << res1 << " " << res2 << endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
solve();
return 0;
}
初始化, 只能求解区间求和
add(i, a[i[ - a[i - 1])
AcWing 243. 一个简单的整数问题2
区间加+区间求和
用补集的思想考虑,纵向考虑。总体减去多余的部分
维护两个前缀和 一个是b1 .... bn, 另一个是i * bi, add参数需要注意,因为他要维护两个前缀和
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
map<pair<int, int>, int> q;
set<pair<int, int>> res;
#define fi first
#define se second
int n, m;
vector<int> t;
vector<ll> tr1, tr2;
int lowbit(int i){return i & -i;}
void add(vector<ll> &tr, int i, ll k){ for(; i <= n; i += lowbit(i)) tr[i] += k; }
ll sum(vector<ll> &tr, int i) {ll r = 0; for(; i > 0; i -= lowbit(i)) r += tr[i]; return r;}
ll prefix_sum(int x){ return sum(tr1, x) * (x + 1) - sum(tr2, x); }
void solve() {
scanf("%d %d", &n, &m);
t.resize(n + 1, 0);
tr1.resize(n + 1, 0);
tr2.resize(n + 1, 0);
for(int i = 1; i <= n; i ++){ scanf("%d", &t[i]);}
for(int i = 1; i <= n; i ++){
int b = t[i] - t[i - 1];
add(tr1, i, b);
add(tr2, i, (ll)i * b);
}
while (m -- )
{
char op[2];
int l, r, d;
scanf("%s%d%d", op, &l, &r);
if (*op == 'Q')
{
printf("%lld\n", prefix_sum(r) - prefix_sum(l - 1));
}
else
{
scanf("%d", &d);
// a[l] += d
add(tr1, l, d), add(tr2, l, l * d);
// a[r + 1] -= d
add(tr1, r + 1, -d), add(tr2, r + 1, (r + 1) * -d);
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
solve();
return 0;
}
AcWing 244. 谜一样的牛
我们需要想一下应该怎么求,怎么推,然后再去怎么写。
第一个牛肯定是0, 我们不知道地一头牛,但是我们知道最后一牛比他高,没有任何一头牛比他矮,倒数第二个牛比他矮,再剩下的数排行第二小,再说剩下的数中的排行。
排定第a[n] + 1,依次往前推,在剩下的所有牛里找到第a[i] + 1小的数,
1.从剩余的数中找出第k小的数。2. 删除某一个数
再去想去优化,其实是平衡数的操作,我们可以用树状数组去做,
起初a1 - an == 1, 维护a1 - an的前缀和, 当我们删除,在某一个位置减去一个1,难点是如何在剩下的数中找到最小的数,我们可以快速 sum 1 - x中剩下多少个数,在剩余中找到一个第k小的数,==》》找到一个最小的x,使得sum(x) == k, 第一个大于等于k的数, 满足单调的,可以二分。
时间复杂度为o(nlog^2),有可能比平衡树还快
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
map<pair<int, int>, int> q;
set<pair<int, int>> res;
#define fi first
#define se second
int n, m;
vector<int> s, a, ans;
int lowbit(int i){return i & -i;}
void add(int i, int k){ for(; i <= n; i += lowbit(i)) s[i] += k; }
int sum(int i) {int r = 0; for(; i > 0; i -= lowbit(i)) r += s[i]; return r;}
int sumall(int i, int j){return sum(j) - sum(i - 1);}
void solve() {
cin >> n;
s.resize(n + 1, 0);
a.resize(n + 1, 0);
ans.resize(n + 1, 0);
for(int i = 2; i <= n; i ++){ cin >> a[i]; }
for(int i = 1; i <= n; i ++){
//每一个总和都等于区间长度
// 维护的是还有几个,然后是前缀和
s[i] = lowbit(i);
}
for(int i = n; i ; i --){
int k = a[i] + 1;
int l = 1, r = n;
while(l < r){
int mid = l + r >> 1;
if(sum(mid) >= k) r = mid;
else l = mid + 1;
}
ans[i] = r;
add(r, -1);
}
for(int i = 1; i <= n; i ++)
cout << ans[i] << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
solve();
return 0;
}
结束!
博客园首页带音乐
侧边栏公告
<!-- 自定义进度条 -->
<div id="myProgressBar" style="display: none;"></div>
<!-- 自定义导航条 -->
<div id="mynavbar" style="margin-top: 0px;">
<div style="position:relative;width:65pc;height:70px;margin:0 auto;">
<a style="width: auto;height: 22px;margin-left: 25px;" class="c-c" href="https://www.cnblogs.com/Additionlly">
<img id="https://userpic.codeforces.org/3566687/title/2637f43cf032d527.jpg" style="width: auto;height: 22px;outline: 0;margin-top: 25px;">
</a>
<div id="mynavbar_menu">
<a href="https://www.cnblogs.com/Additionlly" class="c-c">首页</a>
<a href="https://msg.cnblogs.com/send/Additionlly" class="c-c">联系</a>
<a id="myGayhubUrl" href="https://codeforces.com/profile/Additionlly" class="c-c">Codeforces</a>
<a id="myGayhubUrl" href="https://blog.csdn.net/Water_Sunzhipeng">CSDN</a>
<a href="https://www.cnblogs.com/">博客园</a>
<a href="https://i.cnblogs.com/posts">管理</a>
<a id="aboutMe" href="#">关于</a>
</div>
</div>
</div>
<!-- 自定义头部锚点 -->
<a name="mtop"></a>
<!-- 自定义头部 -->
<div id="myheader">
<!-- 背景图片 -->
<div id="myheader_bg"></div>
<!-- 遮罩层 -->
<div id="myheader_cover" title="点我点我">
<!-- 博客标题 -->
<div id="mypost_title">
<div id="mypost_title_h" style="font-weight: 500;font-size: 21px;"></div>
<div id="mypost_title_f"></div>
<div id="mypost_title_e">
<a href="https://www.cnblogs.com/" class="c-c">暂未分类</a>
</div>
</div>
</div>
</div>
<!-- 为博客底部添加音乐组件 -->
<div id="musicPlayer" class="aplayer"></div>
<link href="https://files.cnblogs.com/files/shwee/APlayer.min_v1.10.1.css" rel="stylesheet">
<script src="https://files.cnblogs.com/files/shwee/APlayer.min_v1.10.1.js"></script>
<script type="text/javascript">
var ap = new APlayer({
element: document.getElementById('musicPlayer'),
narrow: false,
autoplay: true, // 是否自动播放
showlrc: false,
theme: '#F5F5F5', // 插件背景颜色
music: [{
title: '别听悲伤的歌',
author: '格雷西西西',
url: 'https://files.cnblogs.com/files/blogs/824022/111.ppt?t=1723056825&download=true',
pic: 'https://images.cnblogs.com/cnblogs_com/blogs/824022/galleries/2414738/t_240807184749_112.png'
}]
});
ap.init();
</script>
页面定制css
/* 定制公告栏音乐插件的样式 */
.aplayer {
font-family: Arial,Helvetica,sans-serif; /*音乐插件字体*/
margin: 0px; /*音乐插件与公告栏左边的边距,0px就是直接抵到公告栏左边的边上*/
box-shadow: 0 2px 2px 0 rgba(0,0,0,.14), 0 3px 1px -2px rgba(0,0,0,.2), 0 1px 5px 0 rgba(0,0,0,.12);
border-radius: 2px;
overflow: hidden;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
line-height: normal;
}
#sideBar{
display: none;
}
#mainContent{
width: 100%;
box-shadow: 0 0 0;
border-radius: 0px;
opacity: 0;
transition:0.5s;
margin-top:40px;
}
#main{
width: 50%;
background-color: white;
/*max-width: 700px;*/
}
@media screen and (max-width: 1000px) {
#main {width: 100%;}
}
body{
background-image: none;
background-color: white;
font-family: Menlo,Bitstream Vera Sans Mono,DejaVu Sans Mono,Monaco,Consolas,monospace !important;
line-height: 1.8;
}
#cnblogs_post_body{
font-size: 16px;
}
#green_channel{
display: none;
}
#post_next_prev{
display: none;
}
.forFlow img{
margin-top: 0;
}
#cnblogs_post_body img {
max-width: 100%;
}
/* 去除广告 */
#cb_post_title_url{
display: none;
}
#cnblogs_c1{
display: none;
}
#cnblogs_c2{
display: none;
}
#ad_t2{
display: none;
}
#kb_block{
display:none
}
#under_post_news{
display:none
}
#header{
display:none
}
#BlogPostCategory{
display: none;
}
#comment_nav{
display: none;
}
.postDesc{
border-bottom:none;
}
#author_profile_follow{
display: none;
}
/* 自定义样式 */
/* 加载条 */
#myProgressBar{
width: 15%;
height: 2px;
background-color: #eb5055;
position: fixed;
top: 0;
left: 0;
z-index: 999;
}
#nprogress {
pointer-events: none;
}
#nprogress .bar {
background: #eb5055;
position: fixed;
z-index: 1031;
top: 0;
left: 0;
width: 100%;
height: 2px;
}
#nprogress .peg {
display: block;
position: absolute;
right: 0px;
width: 100px;
height: 100%;
box-shadow: 0 0 10px #eb5055, 0 0 5px #eb5055;
opacity: 1.0;
-webkit-transform: rotate(3deg) translate(0px, -4px);
-ms-transform: rotate(3deg) translate(0px, -4px);
transform: rotate(3deg) translate(0px, -4px);
}
#nprogress .spinner {
display: block;
position: fixed;
z-index: 1031;
top: 15px;
right: 15px;
}
#nprogress .spinner-icon {
width: 18px;
height: 18px;
box-sizing: border-box;
border: solid 2px transparent;
border-top-color: #eb5055;
border-left-color: #eb5055;
border-radius: 50%;
-webkit-animation: nprogress-spinner 400ms linear infinite;
animation: nprogress-spinner 400ms linear infinite;
}
.nprogress-custom-parent {
overflow: hidden;
position: relative;
}
.nprogress-custom-parent #nprogress .spinner,
.nprogress-custom-parent #nprogress .bar {
position: absolute;
}
@-webkit-keyframes nprogress-spinner {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
@keyframes nprogress-spinner {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 导航栏 */
#mynavbar{
width: 100%;
height: 70px;
position: fixed;
display: block;
top: 0px;
z-index: 100;
background-color: white;
transition:0.5s ease-in-out;
box-shadow: 0 1px 5px rgba(0,0,0,.1);
}
#mynavbar_menu{
display: inline-block;
width: auto;
position: relative;
float: right;
text-align: right;
line-height: 68px;
}
#mynavbar_menu a{
padding: 0 15px;
font-size: 14px;
outline: 0;
color: #313131;
text-decoration: none;
}
#mynavbar_menu a:hover{
color: #eb5055 !important;
}
/* 头部 */
#myheader{
background-color: #2175bc!important;
margin-top:70px;
position: relative;
width: 100%;
height: 300px;
}
#myheader_bg{
width:100%;
height:300px;
background-position: center;
background-size: cover;
-webkit-filter: blur(3px);
-moz-filter: blur(3px);
filter: blur(3px);
position: absolute;
}
#myheader_cover{
position: relative;
margin-top: 70px;
width: 100%;
height: 300px;
background-color: rgba(0,0,0,.5);
box-shadow: 0 1px 5px rgba(0,0,0,.3);
}
#mypost_title{
position: relative;
top: 105pt;
margin: 0 auto;
padding: 30px 25px 20px;
max-width: 700px;
color: white;
transition:0.5s;
opacity: 0;
}
#mypost_title_e{
margin: 0;
padding: 5px 0 15px;
}
#mypost_title_e a{
border: 1px solid #6fa3ef;
border-radius: 15px;
background: #6fa3ef;
color: #fff;display: inline-block;
margin: 4px 8px 0 0;
padding: 0 15px;
letter-spacing: 0;
font-weight: 600;
font-size: 13px;outline: 0;text-decoration: none;
transition: 0.5s;
}
#mypost_title_e a:before{
content: "# "
}
#mypost_title_e a:hover{
background-color: white;
border: 1px solid white;
color:black;
}
#mypost_title_f a{
color: white;
}
#mypost_title_f a:hover{
text-decoration:none;
}
/* 右侧导航 */
#right_meun{
position: fixed;
top: 100px;
left: 74%;
display: none;
text-align: left;
border-left: 1px solid #ddd;
font-size: 12px;
}
#right_meun li{
list-style: none!important;
}
#right_meun a{
display: inline-table;
margin-left: 5px;
white-space: nowrap;
text-decoration: none;
color: #313131;
outline: 0;
}
#right_meun a:hover{
color: #eb5055;
}
#right_meun>li::before {
position: relative;
top: 0;
left: -4px;
display: inline-block;
width: 7px;
height: 7px;
content: '';
border-radius: 50%;
background-color: #eb5055;
}
/* 底部导航 */
#post-bottom-bar{
position: fixed;
right: 0;
bottom: 0;
left: 0;
z-index: 2;
height: 3pc;
border-top: 1px solid #e0e0e0;
background-color: #fff;
margin: 0;
padding: 0;
transition: 0.5s ease-in-out;
}
#post-bottom-bar a{
text-decoration: none!important;
}
.post-bottom-bar .bottom-bar-inner{
margin: 0 auto;
padding: 0 10px;
max-width: 900px;
}
.bottom-bar-items{
margin: 0 0 0 10px;
color: #313131;
font-size: 14px !important;
line-height: 3pc;float: left;
}
.post-bottom-bar{
margin: 0 0 0 10px;
color: #313131;
font-size: 14px;
line-height: 3pc;
}
.post-bottom-bar .social-share .bottom-bar-item {
padding: 4px;
}
.post-bottom-bar .bottom-bar-item.bottom-bar-facebook a {
background-color: #4267b2;
color: #fff;
}
.post-bottom-bar .social-share .bottom-bar-item a {
padding: 2px 10px;
border-radius: 2px;
}
.bottom-bar-items .post-top-bar-bottom-bar-name {
padding: 0 10px 0 5px;
border-left: 1px solid #e0e0e0;
margin-left: 10px;
}
.bottom-bar-item a{
color: #fff;
text-decoration: none;
}
.bottom-bar-items a {
color: #313131;
}
/* Markdown样式 */
.postBody a {
color: #6fa3ef!important;
text-decoration: none;
border-bottom: 1px solid rgba(0,0,0,.3);
}
.postBody a:hover {
border-bottom: 1px solid rgba(255,255,255,.9);
}
.hljs-keyword, .hljs-selector-tag, .hljs-subst, .hljs-title, .hljs-attr, .hljs-built_in, .hljs-doctag, .hljs-literal, .hljs-section, .hljs-tag{
color: #458;
}
.hljs-name, .hljs-strong {
font-weight: 600;
}
.hljs-code, .hljs-emphasis {
font-style: italic;
}
.hljs-comment, .hljs-quote{
color: #999;
font-style: italic;
}
.hljs-meta {
color: #444;
font-weight: 600;
}
.hljs-meta .hljs-string {
font-weight: 400;
}
.hljs-deletion {
color: #9c333b;
background-color: #f7d4d6;
}
.hljs-addition {
color: #636056;
background-color: #ddf2c9;
}
.hljs-attribute, .hljs-bullet, .hljs-link, .hljs-regexp, .hljs-symbol, .hljs-template-variable, .hljs-variable{
color: #784830;
}
.hljs-string {
color: #784830;
}
.hljs-number {
color: #4b69c6;
}
/* 滚动条样式 */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
::-webkit-scrollbar-track {
border-radius: 2px;
background-color: #f1f1f1;
}
::-webkit-scrollbar-thumb {
border-radius: 2px;
background-color: #888;
}
::-webkit-scrollbar-thumb:hover {
background-color: #555;
}
/* 选区样式 */
::selection {
background-color: #eb5055;
color: white;
}
/* 首页文章条显示优化 */
#post_list {
margin: 0 auto;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
}
.post_item {
background: #fff;
margin: 20px;
width: calc(50% - 40px);
border-radius: 10px;
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
transition: all 0.3s ease;
}
.post_item:hover {
box-shadow: 0 8px 16px rgba(0,0,0,0.2);
}
.post_item .post_item_body {
display: none;
}
.post_item .post_item_title {
font-size: 18px;
font-weight: bold;
color: #333;
margin: 15px;
}
@media screen and (max-width: 768px) {
.post_item {
width: calc(100% - 40px);
}
}
/* 评论区样式 */
.comment_body {
background-color: #f9f9f9;
padding: 10px;
margin: 10px 0;
border-radius: 5px;
}
.comment_body:hover {
background-color: #f1f1f1;
}
.comment_content {
margin: 5px 0;
}
.comment_info {
color: #999;
font-size: 12px;
margin-top: 5px;
display: flex;
justify-content: space-between;
}
.comment_info a {
color: #999;
text-decoration: none;
}
.comment_info a:hover {
color: #333;
}
.comment_form {
margin-top: 20px;
}
.comment_form textarea {
width: 100%;
height: 100px;
border-radius: 5px;
border: 1px solid #ddd;
padding: 10px;
font-size: 14px;
}
.comment_form button {
background-color: #2175bc;
color: #fff;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
}
.comment_form button:hover {
background-color: #195c9a;
}