惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
T
Threatpost
N
News and Events Feed by Topic
PCI Perspectives
PCI Perspectives
V2EX - 技术
V2EX - 技术
D
Docker
G
Google Developers Blog
Microsoft Security Blog
Microsoft Security Blog
N
News and Events Feed by Topic
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Google Online Security Blog
Google Online Security Blog
The GitHub Blog
The GitHub Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Y
Y Combinator Blog
M
MIT News - Artificial intelligence
Blog — PlanetScale
Blog — PlanetScale
博客园 - 司徒正美
T
Troy Hunt's Blog
Webroot Blog
Webroot Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
量子位
Apple Machine Learning Research
Apple Machine Learning Research
H
Help Net Security
F
Full Disclosure
B
Blog
O
OpenAI News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
博客园_首页
Google DeepMind News
Google DeepMind News
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Engineering at Meta
Engineering at Meta
大猫的无限游戏
大猫的无限游戏
Forbes - Security
Forbes - Security
Know Your Adversary
Know Your Adversary
B
Blog RSS Feed
MongoDB | Blog
MongoDB | Blog
Scott Helme
Scott Helme
T
The Exploit Database - CXSecurity.com
博客园 - 聂微东
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
The Last Watchdog
The Last Watchdog
Recorded Future
Recorded Future
IT之家
IT之家
Project Zero
Project Zero
Stack Overflow Blog
Stack Overflow Blog
小众软件
小众软件
Attack and Defense Labs
Attack and Defense Labs
L
Lohrmann on Cybersecurity
SecWiki News
SecWiki News
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com

Makerlife 的小站

2025-2026 赛季 游记 && 退役记 NOIP 2024 游记 集训记录 CSP2024 游记 板子库 动态规划 刷题记录 杂题乱记 数学期望 学习笔记 数论 学习笔记 P6878 [JOI 2020 Final] JJOOII 2 题解 CSP2023 游寄 主定理 CF1695C Zero Path 题解 字符串算法全家桶 学习笔记 AT_ABC306D 题解 2023.06.03 模拟赛 Azure for Students 使用指北 AT_ABC286C 题解 洛谷 AT1898 题解 洛谷 CF1036A 题解 洛谷 CF1040A 题解 洛谷 SP3591 题解 洛谷 AT278 题解 洛谷 CF141B 题解 洛谷 AT2561 题解 洛谷 AT3525 题解 洛谷 CF899B 题解 洛谷 AT4787 题解 洛谷 AT4810 题解 洛谷 SP5450 题解
CF1000F One Occurrence 题解
Makerlife · 2023-12-16 · via Makerlife 的小站

最初的想法是维护每个元素上次出现的下标 lastlast 数组,以样例 1 1 2 3 2 4 为例,维护出来的结果即为 0 1 0 0 3 0,答案就是查找区间 [l,r][l,r] 内是否有 lasti<llast_i<l 的元素。

但这样会出现一个问题:当区间内有元素出现了多次,统计结果会变得不正确。以样例第二组询问为例,a1=a2=1a_1=a_2=1,而 last1=0<1last_1=0<1,看上去可行但实际则出现了两个 11

a={1,1,2,3,2,4}last={INF,1,INF,0,3,0}\begin{aligned} a=&\{1,&1,&2,&3,&2,&4\}\\ last=&\{\text{INF},&1,&\text{INF},&0,&3,&0\} \end{aligned}

由于在维护靠后的 lastlast 时会对前面已经维护的 lastlast 造成影响,故我们需要将询问离线,并按区间右端点排序。保证处理当前询问 [l,r][l,r] 区间时 lastrlast_r 没有被作废。

则程序为单点修改 lastlast 区间查询 lastlast 的最值。值得注意的是维护线段时应保存区间 lastlast 的最小值和该值的下标。区间最小值是为了判断最小的 lastlast 是否在区间内,不是则证明区间内有最小值。最小值下标是为了输出结果。

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
const int N=5e5+10;
int n,m;
int a[N];
int last[N];
int t[N];
int ans[N];
struct qs
{
int l,r,id;
}q[N];
int cmp(qs x,qs y)
{
return x.r<y.r;
}
struct tree
{
int val,pos;
};
struct node
{
int val[N*4],pos[N*4],siz[N*4];
void pushup(int p)
{
if(val[p*2]<val[p*2+1]) val[p]=val[p*2],pos[p]=pos[p*2];
else val[p]=val[p*2+1],pos[p]=pos[p*2+1];
}
void build(int p,int l,int r)
{
if(l==r)
{
val[p]=INF;
pos[p]=l;
return ;
}
int mid=(l+r)>>1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
pushup(p);
}
void modify(int p,int l,int r,int x,int w)
{
if(l==r)
{
val[p]=w;
return ;
}
int mid=(l+r)>>1;
if(x<=mid) modify(p*2,l,mid,x,w);
else modify(p*2+1,mid+1,r,x,w);
pushup(p);
}
tree query(int p,int l,int r,int x,int y)
{
if(x<=l && r<=y)
{
return {val[p],pos[p]};
}
int mid=(l+r)>>1;
tree res={INF,0};
if(x<=mid)
{
tree tmp=query(p*2,l,mid,x,y);
if(tmp.val<res.val)
{
res.val=tmp.val;
res.pos=tmp.pos;
}
}
if(y>=mid+1)
{
tree tmp=query(p*2+1,mid+1,r,x,y);
if(tmp.val<res.val)
{
res.val=tmp.val;
res.pos=tmp.pos;
}
}
return res;
}
}g;
int main()
{
n=read();
for(int i=1;i<=n;i++)
{
a[i]=read();
last[i]=t[a[i]];
t[a[i]]=i;
}
m=read();
for(int i=1;i<=m;i++)
{
q[i].l=read();q[i].r=read();q[i].id=i;
}
sort(q+1,q+m+1,cmp);
g.build(1,1,n);
int j=1;
for(int i=1;i<=n;i++)
{
g.modify(1,1,n,i,last[i]);
if(last[i]!=0) g.modify(1,1,n,last[i],INF);
while(q[j].r==i && j<=m)
{
tree res=g.query(1,1,n,q[j].l,q[j].r);
if(res.val<q[j].l) ans[q[j].id]=a[res.pos];
else ans[q[j].id]=0;
j++;
}
}
for(int i=1;i<=m;i++)
{
cout<<ans[i]<<endl;
}
return 0;
}