[考试总结]noip模拟78
F
开始没啥精神,感觉完全做不动。。。
然后发现这题目也没啥思路。。。
心态稍炸
然后发现答案一共只有 \(n^2\) 种取值,感觉看到曙光。
然后不会。。
然后又发现答案其实只有 \(n\) 种取值,感觉看到希望。
然后还是不会。。。
淦
之后发现一个很妙的XIN队算法,然后对拍没错。
但是,复杂度。。。
\[\mathcal{O(2^n)}\\
n\leq 2000
\]
然后。。。
过了??!?!?!?!?
其实这个题目就是把式子移项,然后对于每一个可能的 \(x\) 进行check
考场代码
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout)
#define debug std::cerr<<"debug"<<endl
#define sb(x) std::cerr<<#x" = "<<x<<' '
#define jb(x) std::cerr<<#x" = "<<x<<endl
#define scanf ak = scanf
#define gec() getchar()
#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; using ll = long long; using ull = unsigned long long; int ak;
class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
{
s = 0; register bool f = 0; register char ch = gc();
while(!isdigit(ch)) f |= ch == '-',ch = gc();
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
}}io;
}
using namespace xin_io;static const int maxn = 1e6+10,inf = 1e9 + 10,two = 2e3+10;ll llinf = 1e18;
namespace xin
{
int a[maxn],b[maxn];
int temp[maxn<<2],zhi = 0;
int n,m,pre;
class xin_data
{
public:
int pos,val;
xin_data(){}
xin_data(int pos,int val):pos(pos),val(val){}
}d[two][two];
bool vis[maxn];
int l,r;
bool dfs(int x,int val)
{
if(x == n + 1) return true;
l = std::lower_bound(d[x]+1,d[x]+n+1,xin_data(0,val),[](xin_data x,xin_data y){return x.val < y.val;}) - d[x];
// sb(x);jb(l);
if(d[x][l].val != val) return false;
r = std::upper_bound(d[x]+1,d[x]+n+1,xin_data(0,val),[](xin_data x,xin_data y){return x.val < y.val;}) - d[x] - 1;
// sb(x); jb(r);
try(i,l,r) if(!vis[d[x][i].pos])
{
vis[d[x][i].pos] = 1;
if(dfs(x+1,val)) return true;
vis[d[x][i].pos] = 0;
}
return false;
}
int out[maxn],ans;
inline short main()
{
freopen("f.in","r",stdin);
freopen("f.out","w",stdout);
io >> n;
try(i,1,n) io >> a[i]; try(i,1,n) io >> b[i];
try(i,1,n)
{
try(j,1,n)
{
d[i][j].pos = j;
d[i][j].val = a[i] xor b[j];
temp[++zhi] = a[i] xor b[j];
}
std::sort(d[i]+1,d[i]+n+1,[](xin_data x,xin_data y)->bool{return (x.val == y.val) ? x.pos < y.pos:x.val < y.val;});
}
try(i,1,n)
{
if(i - 1 and d[1][i].val == d[1][i-1].val) continue;
// jb(d[1][i].val);
memset(vis,0,sizeof(bool) * (n + 1));
if(dfs(1,d[1][i].val)) out[++ans] = d[1][i].val;
}
cout<<ans<<endl;
try(i,1,ans) printf("%d\n",out[i]);
/* try(i,1,n)
{
jb(i);
try(j,1,n)
sb(d[i][j].val),jb(d[i][j].pos);
cout<<endl;
}*/
// dfs(1,9);
return 0;
}
}
signed main() {return xin::main();}
正解:
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout)
#define sb(x) std::cerr<<#x" = "<<x<<' '
#define jb(x) std::cerr<<#x" = "<<x<<endl
#define debug cout<<"debug"<<endl
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
#define gec() getchar()
#define scanf ak = scanf
char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
{
s = 0; register bool f = 0; register char ch= gc();
while(!isdigit(ch)) f |= ch == '-',ch = gc();
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,two = 2e2+10,inf = 1e9+10;
//#define int long long
namespace xin
{
std::unordered_map<int,int>ton;
int a[maxn],b[maxn];
int ans[maxn],zhi = 0;
int out[maxn],cnt = 0;
int n;
auto check = [](int x) -> bool
{
try(i,1,n)
{
ton[x xor b[i]] --;
if(ton[x xor b[i]] < 0) return false;
}
try(i,1,n) if(ton[a[i]]) return false;
return true;
};
inline short main()
{
#ifdef ONLINE_JUDGE
file(f);
#endif
io >> n;
try(i,1,n) io >> a[i]; try(j,1,n) io >> b[j];
try(j,1,n)
{
try(i,1,n) ton[a[i]] = 0;
try(i,1,n) ton[a[i]] ++;
if(check(a[1] xor b[j])) out[++zhi] = a[1] xor b[j];
}
std::sort(out+1,out+zhi+1);
printf("%d\n",zhi);
try(i,1,zhi) printf("%d\n",out[i]);
return 0;
}
}
signed main() {return xin::main();}
s
考场上为了骗分,写了一个假的贪心。
然后骗了 \(40\) 之多。
其实就是让我求一个最小逆序对。
设 \(f_{i,j,k,0/1/2}\) 为选了 \(i\) 个 \(R\),\(j\) 个 \(G\),\(K\) 个 \(B\),然后结尾是什么的答案之后愉快转移。
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout)
#define sb(x) std::cerr<<#x" = "<<x<<' '
#define jb(x) std::cerr<<#x" = "<<x<<endl
#define debug cout<<"debug"<<endl
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
#define gec() getchar()
#define scanf ak = scanf
char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
{
s = 0; register bool f = 0; register char ch= gc();
while(!isdigit(ch)) f |= ch == '-',ch = gc();
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,two = 2e2+10,inf = 1e9+10;
//#define int long long
namespace xin
{
int f[two][two][two][3];
int n,cnt[maxn];
int st[two][two];
char s[maxn];
auto get = [](char ch)
{
if(ch == 'R') return 0;
if(ch == 'G') return 1;
return 2;
};
inline short main()
{
#ifdef ONLINE_JUDGE
file(s);
#endif
scanf("%lld%s",&n,s+1);
try(i,1,n)
{
register int bian = get(s[i]);
st[bian][++cnt[bian]] = i;
}
memset(f,0x3f,sizeof(f));
f[1][0][0][0] = f[0][1][0][1] = f[0][0][1][2] = 0;
try(i,0,cnt[0]) try(j,0,cnt[1]) try(k,0,cnt[2])
{
if(i > 0)
{
int ret = 0;
if(j > 0) ret += j - (std::lower_bound(st[1]+1,st[1]+j+1,st[0][i]) - st[1] - 1);
if(k > 0) ret += k - (std::lower_bound(st[2]+1,st[2]+k+1,st[0][i]) - st[2] - 1);
if(j > 0) f[i][j][k][0] = std::min(f[i][j][k][0],f[i-1][j][k][1] + ret);
if(k > 0) f[i][j][k][0] = std::min(f[i][j][k][0],f[i-1][j][k][2] + ret);
}
if(j > 0)
{
int ret = 0;
if(i > 0) ret += i - (std::lower_bound(st[0]+1,st[0]+i+1,st[1][j]) - st[0] - 1);
if(k > 0) ret += k - (std::lower_bound(st[2]+1,st[2]+k+1,st[1][j]) - st[2] - 1);
if(i > 0) f[i][j][k][1] = std::min(f[i][j][k][1],f[i][j-1][k][0] + ret);
if(k > 0) f[i][j][k][1] = std::min(f[i][j][k][1],f[i][j-1][k][2] + ret);
}
if(k > 0)
{
int ret = 0;
if(i > 0) ret += i - (std::lower_bound(st[0]+1,st[0]+i+1,st[2][k]) - st[0] - 1);
if(j > 0) ret += j - (std::lower_bound(st[1]+1,st[1]+j+1,st[2][k]) - st[1] - 1);
if(i > 0) f[i][j][k][2] = std::min(f[i][j][k][2],f[i][j][k-1][0] + ret);
if(j > 0) f[i][j][k][2] = std::min(f[i][j][k][2],f[i][j][k-1][1] + ret);
}
}
int ans = inf;
try(i,0,2) ans = std::min(f[cnt[0]][cnt[1]][cnt[2]][i],ans);
cout<<ans<<endl;
return 0;
}
}
signed main() {return xin::main();}
y
不会
o
垃圾数据,暴力水过。。
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout)
#define sb(x) std::cerr<<#x" = "<<x<<' '
#define jb(x) std::cerr<<#x" = "<<x<<endl
#define debug cout<<"debug"<<endl
#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
#define gec() getchar()
#define scanf ak = scanf
char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
{
s = 0; register bool f = 0; register char ch= gc();
while(!isdigit(ch)) f |= ch == '-',ch = gc();
while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,two = 1e2+10;
#define int long long
namespace xin
{
int a[maxn],n;
class xin_seg
{
private:
#define ls(fa) (fa << 1)
#define rs(fa) (fa << 1 | 1)
#define up(fa) (t[fa].s = t[ls(fa)].s + t[rs(fa)].s)
public:
class xin_tree{public:int s;}t[maxn];
void build(int fa,int l,int r)
{
if(l == r) return t[fa].s = a[l],void();
register int mid = l + r >> 1;
build(ls(fa),l,mid); build(rs(fa),mid+1,r);
up(fa);
}
void modify(int fa,int l,int r,int pos,int val)
{
if(l == r) return t[fa].s = val,void();
register int mid = l + r >> 1;
if(pos <= mid) modify(ls(fa),l,mid,pos,val);
else modify(rs(fa),mid+1,r,pos,val);
up(fa);
}
int query(int fa,int l,int r,int ql,int qr)
{
if(ql <= l and qr >= r) return t[fa].s;
register int mid = l + r >> 1,ret = 0;
if(ql <= mid) ret += query(ls(fa),l,mid,ql,qr);
if(qr > mid) ret += query(rs(fa),mid+1,r,ql,qr);
return ret;
}
}t;
class xin_query
{
private:
friend bool operator < (const xin_query &x,const xin_query &y){return x.t < y.t;}
public:
int t,l,r,id;
}q[maxn];
int st[maxn],zhi = 0;
class xin_data
{
public:
int id,w;
xin_data(){}
xin_data(int id,int w):id(id),w(w){}
}d[maxn];
std::vector<xin_data> vec[maxn];
int ans[maxn],qnum;
inline short main()
{
#ifdef ONLINE_JUDGE
file(o);
#endif
io >> n >> qnum;
try(i,1,n) io >> a[i]; try(i,1,qnum) io >> q[i].t >> q[i].l >> q[i].r,q[i].id = i;
try(i,1,n)
{
while(zhi and a[i] >= a[st[zhi]]) zhi --;
try(j,1,zhi) vec[i-st[j]].push_back(xin_data(i,a[st[j]]));
st[++zhi] = i;
}
t.build(1,1,n);
std::sort(q+1,q+qnum+1);
try(i,1,qnum)
{
if(q[i].t != q[i-1].t)
{
try(j,q[i-1].t+1,q[i].t)
{
if(j > n) break;
for(auto x : vec[j]) t.modify(1,1,n,x.id,x.w);
}
}
ans[q[i].id] = t.query(1,1,n,q[i].l,q[i].r);
}
try(i,1,qnum) printf("%lld\n",ans[i]);
return 0;
}
}
signed main() {return xin::main();}