专栏文章
题解:P14089 [ICPC 2023 Seoul R] K-Lottery
P14089题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @min0qpoe
- 此快照首次捕获于
- 2025/12/01 18:41 3 个月前
- 此快照最后确认于
- 2025/12/01 18:41 3 个月前
看到这个序列内匹配子串可以想到哈希。
考虑先求出每种排列的逆排列,对逆排列进行哈希。
那么维护一个区间的哈希值可以把它丢到权值线段树上,叶子结点的值表示这个数在区间的排名,线段树上结点的值表示线段树这个区间的哈希值,这个统计的时候顺便维护区间数的个数即可。
那么最后线段树根节点的权值就是整个区间的哈希值。
想一下如何移动区间?
删去左端点和增加右端点均可以直接单点修改,维护每个数的排名可以维护区间减,两个操作都直接线段树即可。
时间复杂度 可以通过。
Code:
CPP#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
#define pii pair<int,int>
#define pb push_back
#define eb emplace_back
#define rep(i,a,b) for (int i=(a);i<=(b);i++)
#define Rep(i,a,b) for (int i=(a);i>=(b);i--)
using namespace std;
using namespace __gnu_pbds;
namespace fast_IO {
// fast_IO...
} using namespace fast_IO;
typedef unsigned long long ull;
const int N=1e6+10;
const int p=13331;
int n,m,e[N];
int k,b[N],len;
vector<int> a[N],c[N];
ull fac[N],sum[N];
gp_hash_table<ull,int> mp;
struct node {
int l,r,cnt,add;
ull val;
#define ls u<<1
#define rs u<<1|1
#define val(u) (t[u].val)
#define cnt(u) (t[u].cnt)
#define add(u) (t[u].add)
}t[N<<2];
void push_up(int u) {
cnt(u)=cnt(ls)+cnt(rs);
val(u)=fac[cnt(rs)]*val(ls)+val(rs);
return ;
}
void push(int u,int x) {
val(u)+=sum[cnt(u)]*x,add(u)+=x;
return ;
}
void push_down(int u) {
if (!add(u)) return ;
push(ls,add(u)),push(rs,add(u)),add(u)=0;
return ;
}
void build(int u,int l,int r) {
t[u].l=l,t[u].r=r;
if (l==r) return ;
int mid=l+r>>1;
build(ls,l,mid),build(rs,mid+1,r);
return ;
}
void insert(int u,int p,int x) {
if (t[u].l==t[u].r) {
val(u)=x,cnt(u)=1;
return ;
}
push_down(u);
int mid=t[u].l+t[u].r>>1;
if (p<=mid) insert(ls,p,x);
else insert(rs,p,x);
return push_up(u);
}
void del(int u,int p) {
if (t[u].l==t[u].r) {
val(u)=cnt(u)=0;
return ;
}
push_down(u);
int mid=t[u].l+t[u].r>>1;
if (p<=mid) del(ls,p);
else del(rs,p);
return push_up(u);
}
void init() {
sort(b+1,b+len+1);
len=unique(b+1,b+len+1)-b-1;
rep(i,1,m) e[i]=lower_bound(b+1,b+len+1,e[i])-b;
fac[0]=1;
rep(i,1,k) fac[i]=fac[i-1]*p;
rep(i,1,m) sum[i]=sum[i-1]+fac[i-1];
build(1,1,len);
return ;
}
void check() {
if (mp.find(val(1))==mp.end()) return ;
int idx=mp[val(1)];
rep(i,1,k) cout<<a[idx][i]<<" ";
cout<<endl;
exit(0);
return ;
}
signed main() {
cin>>k>>n>>m;
rep(i,1,n) {
a[i].resize(k+1);
c[i].resize(k+1);
ull tmp=0;
rep(j,1,k) cin>>a[i][j],c[i][a[i][j]]=j;
rep(j,1,k) tmp=tmp*p+c[i][j];
mp[tmp]=i;
}
rep(i,1,m) cin>>e[i],b[++len]=e[i];
init();
rep(i,1,k) insert(1,e[i],i);
check();
rep(i,k+1,m) {
int lst=i-k;
del(1,e[lst]);
push(1,-1);
insert(1,e[i],k);
check();
}
cout<<0<<endl;
return (0-0);
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...