[考试总结]noip模拟14
咕掉了好长时间,现在终于回来了。。
这次考试炸裂得很完蛋,直接分数上天。
\(T1\) 本来想打一个记忆化搜索,然而老是通过不了样例,然后就挂了,只剩下了垃圾的 \(30pts\) 部分分数。
然而到现在记忆化还是调不出来。。。。
好废啊。
然后 \(T2,T3\) 也只能是暴力收场,垃得一批。
T1:
这个题目就是一个显然的 \(dp\) (只是 \(dp\) 显然,而不是 \(dp\) 方程显然)。。。
然后我们开始疯狂地推 \(dp\) 式子。。。
然后推不出来。。。
你推不出来不会加元吗?????????
这就是推 \(dp\) 方程的真谛
唉
但是我想不出来还有什么状态怎么办呢
那就考虑那些不连续的东西。
虽然他们无法直接转移,但是我们可以离散化
我们将值离散化,然后我们就可以将 \(dp\) 的第二维设置作为值。
我们再来分析问题的实质:
\(\huge{\text{实际上就是要求}min(A_{1\rightarrow i}>B_{i+1})}\)
然后就有了嘛。
然后线段树优化
我从一开始就垃了,巨佬们都想出了线段树优化,而我只能打打暴力维持一下生活这样子
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define debug cout<<"debug"<<endl
namespace xin_io
{
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
#define scanf eat1 = scanf
#define freopen eat2 = freopen
int eat1; FILE *eat2; char buf[1<<20],*p1 = buf,*p2 = buf;
inline void openfile() {freopen("t.txt","r",stdin);} inline void outfile() {freopen("o.txt","w",stdout);}
template<class type>inline type get()
{
type s = 0,f = 1; register char ch = gc();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
while(isdigit(ch)) {s = s * 10 + ch - '0'; ch = gc();}
return s * f;
}
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 0x7f7f7f,mod = 998244353;
#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)
typedef long long ll;
namespace xin
{
int da[maxn],db[maxn],pre_a[maxn],pre_b[maxn];
int n,a[maxn],b[maxn];
int ans = -inf;
int lisan[maxn],zhi = 0;
int tot;
class xin_segment
{
private:
#define ls(fa) (fa << 1)
#define rs(fa) (fa << 1 | 1)
#define up(fa) t[fa].s = std::max(t[ls(fa)].s,t[rs(fa)].s)
inline void down(int fa,int l,int r)
{
if(!t[fa].debt) return ;
t[ls(fa)].debt += t[fa].debt; t[rs(fa)].debt += t[fa].debt;
t[ls(fa)].s += t[fa].debt; t[rs(fa)].s += t[fa].debt;
t[fa].debt = 0;
}
public:
class xin_tree{public:int s,debt;}t[maxn];
void insert(int fa,int l,int r,int pos,int val)
{
if(pos > r or pos < l ) return ;
if(l == r){t[fa].s = std::max(t[fa].s,val); return ;}
register int mid = l + r >> 1;
down(fa,l,r);
insert(ls(fa),l,mid,pos,val); insert(rs(fa),mid+1,r,pos,val);
up(fa);
}
void update(int fa,int l,int r,int ql,int qr,int val)
{
if(qr < l or ql > r) return ;
if(qr >= r and ql <= l)
{
t[fa].s += val; t[fa].debt += val;
return ;
}
register int mid = l + r >> 1;
down(fa,l,r);
update(ls(fa),l,mid,ql,qr,val); update(rs(fa),mid+1,r,ql,qr,val);
up(fa);
}
int query(int fa,int l,int r,int ql,int qr)
{
if(qr < l or ql > r) return -inf;
if(qr >= r and ql <= l) return t[fa].s;
register int mid = l + r >> 1,ret = 0;
down(fa,l,r);
ret = std::max(ret,query(ls(fa),l,mid,ql,qr));
ret = std::max(ret,query(rs(fa),mid+1,r,ql,qr));
return ret;
}
}t;
inline short main()
{
#ifndef ONLINE_JUDGE
openfile();
#endif
n = get<signed>();
try(i,1,n) pre_a[i] = da[i] = get<signed>(),pre_b[i] = db[i] = get<signed>(),lisan[++zhi] = da[i],lisan[++zhi] = db[i];
std::sort(lisan+1,lisan+zhi+1);
int len = std::unique(lisan+1,lisan+zhi+1) - lisan - 1;
try(i,1,n)
{
a[i] = std::lower_bound(lisan+1,lisan+len+1,pre_a[i]) - lisan;
b[i] = std::lower_bound(lisan+1,lisan+len+1,pre_b[i]) - lisan;
// cout<<a[i]<<' '<<b[i]<<endl;
}
try(i,1,n)
{
if(a[i] <= b[i])
{
register int temp = t.query(1,1,len,b[i]+1,len) + 1;
ans = std::max(ans,temp);
t.insert(1,1,len,a[i],temp);
}
else
{
register int temp = t.query(1,1,len,a[i]+1,len) + 1;
ans = std::max(ans,temp);
int zhuan = temp;
temp = t.query(1,1,len,b[i]+1,a[i]) + 1;
ans = std::max(ans,temp);
t.update(1,1,len,b[i]+1,a[i],1);
t.insert(1,1,len,a[i],zhuan);
}
}
cout<<ans<<endl;
return 0;
}
}
signed main() {return xin::main();}
T2:
还没改出来,现在只能拿个 \(40pts\) 暴力分。。。
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define debug cout<<"debug"<<endl
namespace xin_io
{
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
#define scanf eat1 = scanf
#define freopen eat2 = freopen
int eat1; FILE *eat2; char buf[1<<20],*p1 = buf,*p2 = buf;
inline void openfile() {freopen("t.txt","r",stdin);} inline void outfile() {freopen("o.txt","w",stdout);}
template<class type>inline type get()
{
type s = 0,f = 1; register char ch = gc();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
while(isdigit(ch)) {s = s * 10 + ch - '0'; ch = gc();}
return s * f;
}
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 0x7f7f7f7f,mod = 998244353;
#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)
typedef long long ll;
int n,m;
class xin_edge{public:int ver,next;}edge[maxn];
int head[maxn],zhi = 0;
inline void add(int x,int y) {edge[++zhi].ver = y; edge[zhi].next = head[x]; head[x] = zhi;}
int c[maxn];
int d[maxn];
namespace subtask1
{
bool vis[maxn],col[maxn];
void dfs1(int x,int f)
{
d[x] = d[f] + 1;
for(register int i=head[x];i;i=edge[i].next)
{
register int y = edge[i].ver;
dfs1(y,x);
}
}
int q[maxn],zhi = 0;
inline int query(int pos,int len)
{
int ans = 0;
if(!len) return 1;
memset(vis,0,sizeof(bool) * (n + 1)); memset(col,0,sizeof(bool) * (n + 1));
q[++zhi] = pos; vis[pos] = col[c[pos]] = 1; ans = 1;
while(zhi)
{
register int x = q[zhi--];
for(register int i=head[x];i;i=edge[i].next)
{
register int y = edge[i].ver;
if(d[y] - d[pos] > len) continue;
if(!vis[y])
{
vis[y] = 1;
if(!col[c[y]]) col[c[y]] = 1,ans++;
q[++zhi] = y;
}
}
}
return ans;
}
inline short main()
{
try(i,1,n) c[i] = get<signed>();
try(i,2,n)
{
register int x = get<signed>();
add(x,i);
}
dfs1(1,0);
try(que,1,m)
{
register int x = get<signed>(),len = get<signed>();
printf("%d\n",query(x,len));
}
return 0;
}
}
signed main()
{
#ifndef ONLINE_JUDGE
openfile();
#endif
n = get<signed>(); m = get<signed>();
subtask1::main();
return 0;
}
垃圾的我在考场上莫队还打垃了。
T3:
暴力极度好想,就是暴力搜索,然后就愉快有 \(50pts\)
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define debug cout<<"debug"<<endl
namespace xin_io
{
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
#define scanf eat1 = scanf
#define freopen eat2 = freopen
int eat1; FILE *eat2; char buf[1<<20],*p1 = buf,*p2 = buf;
inline void openfile() {freopen("t.txt","r",stdin);} inline void outfile() {freopen("o.txt","w",stdout);}
template<class type>inline type get()
{
type s = 0,f = 1; register char ch = gc();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
while(isdigit(ch)) {s = s * 10 + ch - '0'; ch = gc();}
return s * f;
}
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 0x7f7f7f7f,mod = 998244353;
#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)
typedef long long ll;
namespace xin
{
std::string s;
int len,l;
bool ok = 0;
std::vector<char> a; int zhi = 0,ans = 0;
std::map<std::vector<char>,int>vis;
void dfs(int ms,int pos)
{
if(a.size() == ms)
{
if(!vis[a]) vis[a] = 1,ans++;
return ;
}
for(register int i=pos+1;i<l;++i)
{
a.push_back(s[i]);
dfs(ms,i);
a.pop_back();
}
}
inline short main()
{
#ifndef ONLINE_JUDGE
openfile();
#endif
std::cin>>s>>len;
l = s.size();
for(register int i=1;i<l;++i)
if(s[i] != s[i-1]) ok = 1;
if(!ok){cout<<1<<endl;return 0;}
dfs(len,-1);
cout<<ans<<endl;
return 0;
}
}
signed main() {return xin::main();}
老 \(STL\) 人了
然后考虑正解。。
这就是一道luogu上绿色的模板题嘛 ---赵sir
我又垃了。
好吧,方程就是:
\[f_{i,j} = f_{i-1,j} + f_{i,j-1} - f{p-1,j-1}
\]
表示处理前 \(i\) 个位置,然后长度为 \(j\),\(p\) 就是这个字母上一个出现的位置。
然后就有了:
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define debug cout<<"debug"<<endl
#define int long long
namespace xin_io
{
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
#define scanf eat1 = scanf
#define freopen eat2 = freopen
int eat1; FILE *eat2; char buf[1<<20],*p1 = buf,*p2 = buf;
inline void openfile() {freopen("t.txt","r",stdin);} inline void outfile() {freopen("o.txt","w",stdout);}
template<class type>inline type get()
{
type s = 0,f = 1; register char ch = gc();
while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
while(isdigit(ch)) {s = s * 10 + ch - '0'; ch = gc();}
return s * f;
}
}
using namespace xin_io; static const int maxn = 3e3+10,inf = 0x7f7f7f7f,mod = 998244353;
#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)
typedef long long ll;
namespace xin
{
int f[maxn][maxn];
char s[maxn];
int l,len;
int p[maxn];
int dfs(int i,int j)
{
if(i < j) return 0;
if(f[i][j]) return f[i][j];
if(!i or !j) return 1;
if(p[i]) f[i][j] = (dfs(i-1,j) + dfs(i-1,j-1) - dfs(p[i]-1,j-1) + mod) % mod;
else f[i][j] = (dfs(i-1,j) + dfs(i-1,j-1)) % mod;
return f[i][j] % mod;
}
inline void do_prework()
{
try(i,1,l)
try(j,i+1,l)
if(s[j] == s[i])
{p[j] = i;break;}
}
inline short main()
{
#ifndef ONLINE_JUDGE
openfile();
#endif
scanf("%s%lld",s+1,&len); l = strlen(s+1);
try(i,0,len) f[i][i] = 1;
do_prework();
f[l][len] = dfs(l,len) % mod;
cout<<f[l][len] % mod<<endl;
return 0;
}
}
signed main() {return xin::main();}