[OItiku]八月提高模拟
本文最后更新于 148 天前,其中的信息可能已经有所发展或是发生改变。

一场有趣的比赛

Before the Beginning

转载请将本段放在文章开头显眼处,如有二次创作请标明。
原文链接:https://www.codein.icu/oitiku8mon/

前言

赛上边打边写的题解,所以描述不清,懒得改了。
大致看个意思,直接看代码较好。
最后 A 题70分,B 题90分,C 题30分,暴力甚至拿多了分QAQ
运用了命名空间面向数据编程法。
题目质量不错。
题目链接:https://www.oitiku.com/simulate-contest/1

A

最大后缀值个数,考虑最大后缀值何时取到。
当是一条链时,例如:

$3 2 5 4 1 6 3 2$

当前值等于后缀最大值,说明当前点后没有比当前点大的数。
求出所有路径中有多少个满足的,可以考虑求出某点后第一个比它大的数。
在这之间都是满足的。
题目限制路径一端点为 $1$,枚举后缀最大值点,将贡献计入对应的另一端点。
可以用差分来实现区间操作。
可以拿到链的部分分。

#include <algorithm>
#include <cstdio>
#include <ctype.h>
using namespace std;
const int bufSize = 1e6;
#define DEBUG
inline char nc()
{
#ifdef DEBUG
    return getchar();
#endif
    static char buf[bufSize], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, bufSize, stdin), p1 == p2) ? EOF : *p1++;
}
template<typename T>
inline T read(T &r)
{
    r = 0;
    static char c;
    for (c = nc(); !isdigit(c); c = nc());
    for (; isdigit(c); c = nc()) r = r * 10 + c - 48;
    return r;
}
const int maxn = 1e6 + 100;
int n,fa[maxn];
int w[maxn];
namespace ChainBruteForce
{
    int ans[maxn];
    inline void solve()
    {
        for(int r = 1;r<=n;++r)
        {
            int maxx = 0;
            for(int i = r;i;--i)
            {
                maxx = std::max(maxx,w[i]);
                if(w[i] == maxx) ++ans[r];
            }
        }
        for (int i = 1; i <= n; ++i) printf("%d ",ans[i]);
        puts("");
    }
}
namespace Chain
{
    int rmax[maxn];
    int st[maxn],top;
    int ans[maxn];
    inline void solve()
    {
        for (int i = 1; i <= n; ++i) 
        {
            while(top && w[st[top]] < w[i]) rmax[st[top--]] = i;
            st[++top] = i;
        }
        while (top) rmax[st[top--]] = n + 1;
        for (int i = 1; i <= n; ++i) ans[i]++, ans[rmax[i]]--;
        for (int i = 1; i <= n; ++i) ans[i] += ans[i-1];
        for (int i = 1; i <= n; ++i) printf("%d ",ans[i]);
        putchar('\n');
    }
}
int main()
{
    read(n);
    bool flag = 1;
    for (int i = 2; i <= n; ++i) read(fa[i]),flag &= (fa[i] == i-1 ? 1 : 0);
    for (int i = 1; i <= n; ++i) read(w[i]);
    if (flag) 
    {
#ifdef DEBUG
        ChainBruteForce::solve();
#endif
        Chain::solve();
    }
    return 0;
}

考虑能否将链的做法拓展到树上。
如果依然使用 $rmax$ 的做法,显然儿子并非单一的,无法实现。
考虑从根到节点,维护一个单调不增栈,以该节点为端点的答案就是栈的大小。
对于栈中每个节点,在当前端点限制下,它的后面都没有比它更大的儿子。
因此就是树上单调栈了。
然而回溯似乎并不好做,开了个 vector 暴力记录,似乎会出锅,不管了。

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast","-funroll-loops")
#pragma GCC target("ssse3","sse3","sse2","sse","avx2","avx")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <cstdio>
#include <vector>
#include <algorithm>
#include <ctype.h>
const int bufSize = 1e6;
using namespace std;
//#define DEBUG
inline char nc()
{
    #ifdef DEBUG
    return getchar();
    #endif
    static char buf[bufSize], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, bufSize, stdin), p1 == p2) ? EOF : *p1++;
}
template<typename T>
inline T read(T &r)
{
    static char c;
    static int flag;
    flag = 1, r = 0;
    for (c = nc(); !isdigit(c); c = nc()) if (c == '-') flag = -1;
    for (; isdigit(c); c = nc()) r = r * 10 + c - 48;
    return r *= flag;
}
const int maxn = 1e6 + 100;
struct node
{
    int to,next;
}E[maxn];
int head[maxn];
inline void add(const int &x,const int &y)
{
    static int tot = 0;
    E[++tot].next = head[x],E[tot].to = y,head[x] = tot;
}
int n, fa[maxn], w[maxn];
int st[maxn], top;
int ans[maxn];
void dfs(int u)
{
    int otop = top;
    vector<pair<int, int> > mem;
    while (top && w[st[top]] < w[u]) mem.push_back(make_pair(top, st[top])), --top;
    st[++top] = u;
    ans[u] = top;
    for (int p = head[u]; p; p = E[p].next)
    {
        int v = E[p].to;
        dfs(v);
    }
    for (vector<pair<int, int> >::iterator it = mem.begin(); it != mem.end(); ++it) st[it->first] = it->second;
    top = otop;
}
namespace Chain2
{
    int st[maxn],top;
    inline void solve()
    {
        for (int i = 1; i <= n; ++i) 
        {
            while(top && w[st[top]] < w[i]) --top;
            st[++top] = i;
            printf("%d ",top);
        }
        puts("");
    }
}
int main()
{
    freopen("suffix.in","r",stdin);
    freopen("suffix.out","w",stdout);
    read(n);
    bool flag = 1;
    for (int i = 2; i <= n; ++i) read(fa[i]), add(fa[i], i), flag &= (fa[i] == i - 1 ? 1 : 0);
    for (int i = 1; i <= n; ++i) read(w[i]);
    if (flag) Chain2::solve();
    else
    {
        dfs(1);
        for (int i = 1; i <= n; ++i) printf("%d ", ans[i]);
    }
    return 0;
}

B

题意相当清楚。
先随手打个 $O(n^3)$ 的暴力出来:

const int maxn = 1e6 + 100;
int n,x,a[maxn];
int main()
{
    read(n),read(x);
    for (int i = 1; i <= n; ++i) read(a[i]);
    int ans = 0;
    for(int l = 1;l<=n;++l) for(int r = l;r<=n;++r)
    {
        int maxx = 0,minn = 1<<30;
        for(int i = l;i<=r;++i) maxx = std::max(maxx,a[i]),minn = std::min(minn,a[i]);
        if(maxx + minn == x) ++ans;
    }
    printf("%d\n",ans);
    return 0;
}

固定左端点,移动右端点,可以直接 $O(1)$ 更新最大最小值,优化至 $O(n^2)$。

int n,x,a[maxn];
int main()
{
    read(n),read(x);
    for (int i = 1; i <= n; ++i) read(a[i]);
    int ans = 0;
    for(int l = 1;l<=n;++l) 
    {
        int maxx = 0,minn = 1<<30;
        for (int r = l; r <= n; ++r)
        {
            maxx = std::max(maxx, a[r]), minn = std::min(minn, a[r]);
            if (maxx + minn == x) ++ans;
        }
    }
    printf("%d\n",ans);
    return 0;
}

瓶颈在于移动右端点,考虑如何减少部分复杂度。
最大值单调递增,最小值单调递减,不具备单调性,二分是行不通的。但可以加一个小剪枝。

if(maxx > x) break;

考虑很多点对最大值、最小值无影响,是可以跳过的。
每次跳到下一个会影响的点,即可优化部分常数。

单调栈预处理一下。

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast","-funroll-loops")
#pragma GCC target("ssse3","sse3","sse2","sse","avx2","avx")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <cstdio>
#include <algorithm>
#include <ctype.h>
const int bufSize = 1e6;
using namespace std;
inline char nc()
{
    #ifdef DEBUG
    return getchar();
    #endif
    static char buf[bufSize], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, bufSize, stdin), p1 == p2) ? EOF : *p1++;
}
template<typename T>
inline T read(T &r)
{
    static char c;
    static int flag;
    flag = 1, r = 0;
    for (c = nc(); !isdigit(c); c = nc()) if (c == '-') flag = -1;
    for (; isdigit(c); c = nc()) r = r * 10 + c - 48;
    return r *= flag;
}
const int maxn = 1e6 + 100;
int n,x,a[maxn];
namespace Bruteforce
{
    inline void solve()
    {
        long long ans = 0;
        for (int l = 1; l <= n; ++l)
        {
            int maxx = 0, minn = 1 << 30;
            for (int r = l; r <= n; ++r)
            {
                maxx = std::max(maxx, a[r]), minn = std::min(minn, a[r]);
                if (maxx > x) break;
                if (maxx + minn == x) ++ans;
            }
        }
        printf("%lld\n", ans);
    }
}
namespace Sol2
{
    int rmax[maxn],rmin[maxn];
    int st[maxn],top;
    inline void solve()
    {
        for (int i = 1; i <= n; ++i)
        {
            while (top && a[st[top]] > a[i]) rmin[st[top--]] = i;
            st[++top] = i;
        }
        while (top) rmin[st[top--]] = n + 1;
        for (int i = 1; i <= n; ++i)
        {
            while (top && a[st[top]] < a[i]) rmax[st[top--]] = i;
            st[++top] = i;
        }
        while (top) rmax[st[top--]] = n + 1;
        long long ans = 0;
        for (int l = 1; l <= n; ++l)
        {
            int maxx = l, minn = l;
            int r = l;
            while (r <= n)
            {
                if (a[maxx] > x) break;
                if (a[minn] + a[maxx] == x) ans += std::min(rmin[minn], rmax[maxx]) - r;
                r = std::min(rmin[minn], rmax[maxx]);
                if (a[r] > a[maxx]) maxx = r;
                if (a[r] < a[minn]) minn = r;
            }
        }
        printf("%lld\n", ans);

    }
}
int main()
{
    freopen("interval.in","r",stdin);
    freopen("interval.out","w",stdout);
    read(n), read(x);
    for (int i = 1; i <= n; ++i) read(a[i]);
    if (n <= 5000) Bruteforce::solve();
    else Sol2::solve();
    return 0;
}

C

显然有 $O(nm)$ 的暴力做法,即枚举块长验证。
先打了再说。

namespace Bruteforce
{
inline int calcbel(int x) { return (x - 1) / B + 1; }
inline int calcL(int x) { return B * (x - 1) + 1; }
inline int calcR(int x) { return B * x; }
inline void solve()
{
    for (B = 1; B <= n; ++B)
    {
        long long ans = 0;
        for (int i = 1; i <= m; ++i)
        {
            int lbel = calcbel(Q[i].l), rbel = calcbel(Q[i].r);
            if (lbel == rbel) ans += Q[i].r - Q[i].l + 1;
            else
            {
                ans += rbel - lbel - 1;
                ans += calcR(lbel) - Q[i].l + 1;
                ans += Q[i].r - calcL(rbel) + 1;
            }
        }
        printf("%lld ",ans);
    }
}
}  // namespace Bruteforce
int main()
{
    read(n), read(m);
    for (int i = 1; i <= m; ++i) read(Q[i].l), read(Q[i].r);
    Bruteforce::solve();
    return 0;
}

暴力30分拿到手。

考虑整除有一定的神奇性质,即一个询问的区间,对于某段连续的块长 $B$,除出来是一样的。

每块:$[(i-1) \times B + 1,i \times B]$

例如 $\lceil \dfrac{L}{B} \rceil = i$,那么对于这段连续的 $B$,左边残余块的贡献都是 $i \times B – L + 1$,将 $i \times B$ 分离仅记录 $i$,即可利用差分来维护。

确定 $i$ 与 $B$ 时,贡献为:$\sum i \times B – L + 1$ ,化简为 $num \times i \times B – (suml(R) – suml(L-1)) + num$

而 $\lfloor \dfrac{R}{B} \rfloor = j$,同理贡献为 $R – j \times B$,也可以利用差分维护。

然而复杂度似乎有点高,可以预处理 $cnt(L)$ 与 $cnt(R)$,枚举 $i,j$,复杂度降为调和级数,即 $O(n \log n)$

现在难点在于统计整块的贡献。

可以发现处理的的 $i,j$ 其实就是所属的块的序号,每个询问的整块贡献为 $j – i – 1$,可以将常数提出,然后在枚举 $i,j$ 时记录贡献。

即已知 $i,B$ 时,$ans[L:R] += -i \times num$

$ans[L:R] += j \times num$

最后总答案减去一个 $m$

然而……

经过尝试之后,发现这个办法没法维护块内贡献。

最后白耗一小时,还是只有30pts暴力分。

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast","-funroll-loops")
#pragma GCC target("ssse3","sse3","sse2","sse","avx2","avx")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include <cstdio>
#include <algorithm>
#include <ctype.h>
const int bufSize = 1e6;
#define DEBUG
inline char nc()
{
    #ifdef DEBUG
    return getchar();
    #endif
    static char buf[bufSize], *p1 = buf, *p2 = buf;
    return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, bufSize, stdin), p1 == p2) ? EOF : *p1++;
}
inline void read(char *s)
{
    static char c;
    for (; !isalpha(c); c = nc());
    for (; isalpha(c); c = nc()) *s++ = c;
    *s = '\0';
}
template<typename T>
inline T read(T &r)
{
    static char c;
    static int flag;
    flag = 1, r = 0;
    for (c = nc(); !isdigit(c); c = nc()) if (c == '-') flag = -1;
    for (; isdigit(c); c = nc()) r = r * 10 + c - 48;
    return r *= flag;
}
const int maxn = 1e6 + 100;
int n,m,B;
struct query
{
    int l,r;
}Q[maxn];

namespace Bruteforce
{
inline int calcbel(int x) { return (x - 1) / B + 1; }
inline int calcL(int x) { return B * (x - 1) + 1; }
inline int calcR(int x) { return B * x; }
inline void solve()
{
    for (B = 1; B <= n; ++B)
    {
        long long ans = 0;
        for (int i = 1; i <= m; ++i)
        {
            int lbel = calcbel(Q[i].l), rbel = calcbel(Q[i].r);
            if (lbel == rbel) ans += Q[i].r - Q[i].l + 1;
            else
            {
                ans += rbel - lbel - 1;
                ans += calcR(lbel) - Q[i].l + 1;
                ans += Q[i].r - calcL(rbel) + 1;
            }
        }
        printf("%lld ",ans);
    }
    puts("");
}
}  // namespace Bruteforce
namespace sol
{
    int cntl[maxn],cntr[maxn];
    long long suml[maxn],sumr[maxn];
    inline void solve()
    {
        for (int i = 1; i <= m; ++i) cntl[Q[i].l]++, cntr[Q[i].r]++;
        for (int i = 1; i <= n + 5; ++i) suml[i] = 1ll * cntl[i] * i,sumr[i] = 1ll * cntr[i] * i;
        for (int i = 1; i <= n + 5; ++i) cntl[i] += cntl[i - 1], cntr[i] += cntr[i - 1];
        for (int i = 1; i <= n + 5; ++i) suml[i] += suml[i-1],sumr[i] += sumr[i-1];
        for (int B = 1; B <= n; ++B)
        {
            long long ans = 0;
            for (int i = 1; i <= n; ++i)
            {
                int l = (i - 1) * B + 1, r = std::min(i * B,n);
                if(l > n) break;
                int num = cntl[r] - cntl[l - 1];
                ans += 1ll * r * num - (suml[r] - suml[l-1]) + num;
                ans += -i * num;
                num = cntr[r] - cntr[l-1];
                ans += (sumr[r] - sumr[l-1]) - 1ll * l * num + num;
                ans += i * num;
            }
            printf("%lld ",ans - m);
        }
    }
}
int main()
{
    freopen("block.in","r",stdin);
    freopen("block.out","w",stdout);
    read(n), read(m);
    for (int i = 1; i <= m; ++i) read(Q[i].l), read(Q[i].r);
    if(n <= 5000 && m <= 5000) Bruteforce::solve();
    else sol::solve();
    return 0;
}
本文标题:[OItiku]八月提高模拟
本文作者:Clouder
本文链接: https://www.codein.icu/oitiku8mon/
转载请标明。

评论

  1. feiko
    5月前
    2020-9-03 3:54:30

    太强了

发送评论 编辑评论

|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇