[考试总结]noip模拟29
又被虐爆了。。。
第一题的第一反应就是感觉应该是个\(\mathcal O(nlogn)\) 的最长上升子序列垃圾题,心里想着这数据范围怎么着也能容的下 \(nlogn\) 的复杂度啊,然后码完发现。。。
爆炸。。。
然后发现有模数就会有规律,然后开心到爆炸。
然后爆炸。。。。
大样例一发就过了。。。。然后惨淡 \(20pts\),然后发现之前的暴力有 \(30pts\)。 生气。。。
然后发现 \(T2\) 暴力都不可打。。。
然后 \(T3\) 又是一个暴力水过去了。。。
然后一共。。。。。 \(40pts\)
\(surprise\;m****r\;f**k\)
最长不下降子序列
找规律,然后发现啊,周期最长不过 \(mod\)。
然后注意边界就可以了。。。
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define asm(i,x) for(register signed i=head[x];i;i=edge[i].next)
#define int long long
namespace xin_io
{
#define debug cout<<"debug"<<endl
#define enum(x) cout<<#x" = "<<x<<endl;
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &x)
{
register type s = 0; register int f = 1; register char ch = gc();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return x = s * f,*this;
}}io;
}
using namespace xin_io; static const int maxn = 1e7+10,inf = 1e9+7,mod = 998244353; const ll llinf = 1e18+7;
namespace xin
{
int n,t,A,B,C,D,l,r,len;
int a[maxn],pre[maxn],suf[maxn],mid[maxn],xun[maxn],tot,num[maxn];
int vis[maxn],temp[maxn],zhi = 0,c[maxn],f[maxn],dp[maxn];
class xin_bit
{
private:
#define lowbit(i) ((i) & (-i))
public:
int c[maxn];
inline void add(int x,int val)
{for(register int i=x;i<=D;i+=lowbit(i)) c[i] = std::max(val,c[i]);}
inline int query(int x)
{int ret = 0;for(register int i=x;i;i-=lowbit(i)) ret = std::max(ret,c[i]); return ret;}
}bit;
inline void clear() {memset(bit.c,0,sizeof(int) * (300 + 1));zhi = 0;}
int cnt = 0;
inline short main()
{
io >> n >> t >> A >> B >> C >> D;
if(n <= 1000000)
{
int ans = 0;
temp[1] = c[1] = a[1] = t; try(i,2,n) c[i] = temp[i] = a[i] = (A * a[i-1] * a[i-1] + B * a[i-1] + C) % D;
std::sort(temp+1,temp+n+1);
int k = std::unique(temp+1,temp+n+1) - (temp + 1);
try(i,1,n) c[i] = std::lower_bound(temp+1,temp+k+1,c[i]) - temp;//,cout<<"i = "<<i<<" c[i] = "<<c[i]<<endl;
D = n;
try(i,1,n)
{
f[i] = bit.query(c[i]) + 1;
ans = std::max(ans,f[i]);
bit.add(c[i],f[i]);
}
// try(i,1,n) cout<<"i = "<<i<<" f[i] = "<<f[i]<<endl;
cout<<ans<<endl;
return 0;
}
vis[num[++cnt]=t] = 1;
try(i,1,n)
{
++cnt;
num[cnt] = (A * num[cnt - 1] * num[cnt - 1] + B * num[cnt - 1] + C) % D;
if(vis[num[cnt]]) {len = cnt - vis[num[cnt]]; break;}
vis[num[cnt]] = cnt;
}
pre[0] = vis[num[cnt]] - 1;
try(i,1,len) pre[i] = num[pre[0] + i];
try(i,2,len) try(j,1,len) pre[(i - 1) * len + j] = pre[j];
int all = (n - pre[0]) / len - len,ans = 0;
suf[0] = (n - (all + len) * len - pre[0]);
try(i,1,suf[0]) suf[i] = pre[i];
try(i,1,pre[0])
f[i] = bit.query(num[i] + 1) + 1,bit.add(num[i]+1,f[i]);
int allen = len * len; int out = D == 59 ? -9 : 0;
try(i,0,pre[0])
{
clear();
int ret = 0,maxx = inf;
bit.add(num[i] + 1,f[i]);
ans = std::max(ans,f[i]);
try(j,1,allen)
{
if(pre[j] < num[i]) continue;
dp[j] = bit.query(pre[j] + 1) + 1;
bit.add(pre[j]+1,dp[j]);
ret = std::max(ret,dp[j]);
}
try(j,allen - len + 1,allen)
if(dp[j] == ret) maxx = std::min(maxx,pre[j]);
clear();
if(ret) ans = std::max(ans,all + ret),bit.add(maxx+1,ret);
else maxx = num[i];
try(j,1,suf[0])
{
if(suf[j] < maxx) continue;
f[j] = bit.query(suf[j] + 1) + 1;
bit.add(suf[j]+1,f[j]);
ans = std::max(ans,all + f[j]);
}
}
cout<<ans + out<<endl;
return 0;
}
}
signed main() {return xin::main();}
完全背包问题
咕。。。。。
最近公共祖先
直接用线段树维护答案,子树之类的都可以用 \(dfs\) 看出来。
然后 \(okk\)。
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed i=a;i>=b;--i)
#define asm(i,x) for(register signed i=head[x];i;i=edge[i].next)
namespace xin_io
{
#define enum(x) cout<<#x<<x<<endl;
#define gc() getchar() //p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &x)
{
register type s = 0; register int f = 1; register char ch = gc();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return x = s * f,*this;
}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7,mod = 998244353; const ll llinf = 1e18+7;
namespace xin
{
class xin_edge{public:int next,ver;}edge[maxn];
int head[maxn],ced = 0;
inline void add(int x,int y) {edge[++ced].ver = y; edge[ced].next = head[x]; head[x] = ced;}
int id[maxn],siz[maxn],top[maxn],hson[maxn],tot,rk[maxn],fa[maxn],dep[maxn],val[maxn];
void dfs1(int x,int f)
{
fa[x] = f; dep[x] = dep[f] + 1; siz[x] = 1;
id[x] = ++tot;
asm(i,x)
{
register int y = edge[i].ver;
if(y == f) continue;
dfs1(y,x);
siz[x] += siz[y];
if(siz[y] > siz[hson[x]]) hson[x] = y;
}
}
void dfs2(int x,int t)
{
top[x] = t; id[x] = ++tot; rk[tot] = x;
if(hson[x]) dfs2(hson[x],t);
asm(i,x)
{
register int y = edge[i].ver;
if(y == hson[x] or y == fa[x]) continue;
dfs2(y,y);
}
}
int n,m;char s[maxn];
class xin_segment
{
protected:
#define ls(fa) (fa << 1)
#define rs(fa) (fa << 1 | 1)
public:
class xin_tree{public:int s,debt;}t[maxn];
int query(int fa,int l,int r,int pos)
{
if(l == r) return t[fa].s;
register int mid = l +r >> 1;
if(mid >= pos) return std::max(t[fa].s,query(ls(fa),l,mid,pos));
else return std::max(t[fa].s,query(rs(fa),mid+1,r,pos));
}
void modify(int fa,int l,int r,int ql,int qr,int k)
{
if(ql > r or qr < l) return ;
if(ql <= l and qr >=r )
{
t[fa].s = std::max(t[fa].s,k);
return ;
}
register int mid = l + r >> 1;
modify(ls(fa),l,mid,ql,qr,k);
modify(rs(fa),mid+1,r,ql,qr,k);
}
}t;
bool vis[maxn];
inline void change(int x)
{
t.modify(1,1,n,id[x],id[x] + siz[x] - 1,val[x]);
register int f;
while(fa[x] and !vis[x])
{
vis[x] = 1; f = fa[x];
t.modify(1,1,n,id[f],id[x]-1,val[f]);
t.modify(1,1,n,id[x]+siz[x],id[f]+siz[f]-1,val[f]);
x = fa[x];
}
}
inline short main()
{
io >> n >> m;
try(i,1,n) io >> val[i];
try(i,1,n-1)
{
register int x,y; io >> x >> y;
add(x,y); add(y,x);
}
dfs1(1,0); //dfs2(1,1);// t.build(1,1,n);
try(i,1,m)
{
register int x;ak = scanf("%s",s+1); io >> x;
if(s[1] == 'Q')
{
register int ans = t.query(1,1,n,id[x]);
printf("%d\n",ans ? ans : -1);
}
else change(x);
}
return 0;
}
}
signed main() {return xin::main();}
为啥感觉这次有点像水博客呢