我是靠谱客的博主 激情爆米花,这篇文章主要介绍loj #6435. 「PKUSC2018」星际穿越题意前言题解,现在分享给大家,希望可以做个参考。

题意

自己看吧

前言

pkusc这题的阴影太大,现在才做回。。
现在想起来,自己的方法过于复杂,并且忘记了使用标记永久化使得代码量巨增。。调不出来也是有原因的

题解

相比起我原来的方法,现在有一个很巧妙的
显然的结论,一个点只会往右边跳一次
然后我们发现这个跳一次非常地难搞。。
考场上我写得是两颗线段树搞来搞去。。搞得我头都大了
我们考虑,其实往右跳除了第一次都是不用代价的,因为你可以直接跳到这个点的右边啊。
因此,我们我们对于一个点,记录一个 mn m n ,表示他(可以先右跳一步)往左跳一步能到的最左
然后如果往右跳不算次数的话,直接从 mn m n 这里转移过来就可以了
至于查询的时候,也挺巧妙的
我们查询的是 root[l[x]] r o o t [ l [ x ] ]
我们假设先跳到这里,如果他往右跳了,那么就相当于第一步跳到那里就可以了
当然,答案要加上 rl+1 r − l + 1

CODE:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include<cstdio> #include<algorithm> #include<iostream> #include<cstring> using namespace std; typedef long long LL; const int N=300005; int n,q; int a[N]; int mn[N]; LL c[N*40],lzy[N*40]; int s1[N*40],s2[N*40]; int num=0; void change (int &now,int l,int r,int L,int R) { num++; c[num]=c[now];lzy[num]=lzy[now];s1[num]=s1[now];s2[num]=s2[now]; now=num; if (l==L&&r==R) { lzy[now]++; return ; } c[now]=c[now]+(R-L+1); int mid=(l+r)>>1; if (R<=mid) change(s1[now],l,mid,L,R); else if (L>mid) change(s2[now],mid+1,r,L,R); else change(s1[now],l,mid,L,mid),change(s2[now],mid+1,r,mid+1,R); } LL ans; void ask (int now,int l,int r,int L,int R) { //printf("YES:%lld %lld %lld %lld %lld %lldn",l,r,L,R,lzy[now],c[now]); ans=ans+lzy[now]*(R-L+1); if (l==L&&r==R) {ans=ans+c[now];return ;} int mid=(l+r)>>1; if (R<=mid) ask(s1[now],l,mid,L,R); else if (L>mid) ask(s2[now],mid+1,r,L,R); else ask(s1[now],l,mid,L,mid),ask(s2[now],mid+1,r,mid+1,R); } int rt[N]; LL gcd (LL x,LL y) { return x==0?y:gcd(y%x,x); } int read() { char ch=getchar();int x=0; while (ch<'0'||ch>'9') ch=getchar(); while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x; } int main() { n=read(); for (int u=2;u<=n;u++) a[u]=read(); mn[n]=a[n]; for (int u=n-1;u>=1;u--) mn[u]=min(a[u],mn[u+1]); for (int u=2;u<=n;u++) { rt[u]=rt[mn[u]]; change(rt[u],1,n,1,u-1); } q=read(); for (int u=1;u<=q;u++) { int l,r,x; l=read();r=read();x=read(); ans=(r-l+1); if (l<a[x]) ask(rt[a[x]],1,n,l,min(r,a[x]-1)); LL b=(r-l+1); LL d=gcd(b,ans); printf("%lld/%lldn",ans/d,b/d); } return 0; }

最后

以上就是激情爆米花最近收集整理的关于loj #6435. 「PKUSC2018」星际穿越题意前言题解的全部内容,更多相关loj内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(66)

评论列表共有 0 条评论

立即
投稿
返回
顶部