题目描述
这道题的意思和D题Jobs (Easy Version)大致是一致的,但它之所以称为 hard 是因为的他变量的取值大,即D题擦边过的那些基本不靠谱,下面是中文翻译:
分析一波
他要求的是满足公司工作要求得到offer的总数,再进行一段迷惑操作。
如果我们按一个个对比3个值,那怎么看都是TLE的。我们先将他看做D题,将他先用2维表示(三维类似于,这里懒得画doge)
这里看到蓝色的区域被包括了,就是直接被刀了。也不难看出,x足够小就可以存活下来,y足够小也可以存活,z就自己推一下。那么利用差分的方法,我们将图包括的地方标记一下。
这里在极端处表上1,交界处表上-1,因为先根据1的传递(前缀和),防止中间包括的部分被多算,所以减去,即平行于x轴这几条从开端开始一直是1结束至第一个-1,然后为什么后面都是1+(-1)了 ? 因为当你做平行y轴的传递时,最底层的1向上扩散(前缀和),把0覆盖掉也变成了1,这样就去掉了重复的叠加。至此,只要我们按照图上的x,y,(z)的关系来排序,再标点,查询即可得出有无得到公司的offer。Z轴的话,因为只有400的数据范围,我们可以考虑切层,也就是转化为400个二维的。
由于考虑到不是每一层都要用的,就是n没有那么大而且z也可能相等。所以我们计算的数量可以给出一个式子:
O( n m log m + + q)
最后的代码环节
先给出题目自带的代码
In this problem, the IQ, EQ, and AQ of these qq friends are generated as below.
First, register an \texttt{mt19937}mt19937 random engine \texttt{rng}rng with the \texttt{seed}seed and a uniform integer distribution object.
#include <random>
std::mt19937 rng(seed);
std::uniform_int_distribution<> u(1,400);
Then, the value of IQ, EQ, and AQ are generated as follows.
int lastans=0;
for (int i=1;i<=q;i++)
{
int IQ=(u(rng)^lastans)%400+1; // The IQ of the i-th friend
int EQ=(u(rng)^lastans)%400+1; // The EQ of the i-th friend
int AQ=(u(rng)^lastans)%400+1; // The AQ of the i-th friend
lastans=solve(IQ,EQ,AQ); // The answer to the i-th friend
}
将他扩散成3维
for(int i=1;i<=400;i++)
for(int j=1;j<=400;j++)
for(int k=1;k<=400;k++)
unv[i][j][k]+=unv[i-1][j][k];
for(int i=1;i<=400;i++)
for(int j=1;j<=400;j++)
for(int k=1;k<=400;k++)
unv[i][j][k]+=unv[i][j-1][k];
for(int i=1;i<=400;i++)
for(int j=1;j<=400;j++)
for(int k=1;k<=400;k++)
unv[i][j][k]+=unv[i][j][k-1];
完整代码献上
#include<bits/stdc++.h>
#include <random>
using namespace std;
template<class T>inline void read(T&x){//快读
char c,last=' ';
while(!isdigit(c=getchar()))last=c;
x=c^48;
while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+(c^48);
if(last=='-')x=-x;
}
#define P pair<int,int>
#define X first
#define Y second
const int MAXN=4e2+5,mod=998244353;
int n,q;
int a[MAXN][MAXN][MAXN];
vector<pair<int,P>>v;
set<P>st;
int qpow(int x,int p){//快速幂
int ret=1;
for(;p;x=1ll*x*x%mod,p>>=1)if(p&1)ret=1ll*ret*x%mod;
return ret;
}
P Pre(P p){
set<P>::iterator it=st.lower_bound(p);
--it;
return *it;
}
P Next(P p){
return *st.upper_bound(p);
}
int main()
{
read(n),read(q);
for(int i=1,m;i<=n;++i){
read(m);
vector<pair<int,P>>().swap(v);
for(int k,x,y;m--;){
read(k),read(x),read(y);
v.push_back(make_pair(k,P(x,y)));
}
sort(v.begin(),v.end());
st.clear();
st.insert(P(0,401));
st.insert(P(401,0));
for(int i=0,k;i<v.size();++i){
k=v[i].X;
P p=v[i].Y;
set<P>::iterator it=st.upper_bound(p);
--it;
if(it->Y<=p.Y)continue;
++a[k][Next(*it).X][it->Y];
st.insert(p);
--a[k][p.X][it->Y];
while(Next(p).Y>=p.Y){
P nxt=Next(p);
--a[k][nxt.X][nxt.Y],++a[k][Next(nxt).X][nxt.Y];
st.erase(nxt);
}
++a[k][p.X][p.Y],--a[k][Next(p).X][p.Y];
}
}
for(int k=1;k<=400;++k){
for(int x=1;x<=400;++x){
for(int y=1;y<=400;++y){
a[k][x][y]+=a[k-1][x][y];
}
}
}
for(int k=1;k<=400;++k){
for(int x=1;x<=400;++x){
for(int y=1;y<=400;++y){
a[k][x][y]+=a[k][x-1][y];
}
}
}
for(int k=1;k<=400;++k){
for(int x=1;x<=400;++x){
for(int y=1;y<=400;++y){
a[k][x][y]+=a[k][x][y-1];
}
}
}
int seed;read(seed);
std::mt19937 rng(seed);
std::uniform_int_distribution<>u(1,400);
int lastans=0,ans=0;
for(int i=1;i<=q;i++){
int IQ=(u(rng)^lastans)%400+1;
int EQ=(u(rng)^lastans)%400+1;
int AQ=(u(rng)^lastans)%400+1;
lastans=a[IQ][EQ][AQ];
ans=(ans+1ll*lastans*qpow(seed,q-i)%mod)%mod;
}
cout<<ans<<'\n';
return 0;
}