赛时rank11,T1 30,T2 0,T3 20,T4 20
T1 活动投票
摩尔投票模板题
点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
using ll=long long;using ull=unsigned long long;
#ifdef LOCAL
FILE *InFile = infile("in.in"),*OutFile = outfile("out.out");
// FILE *ErrFile=errfile("err.err");
#else
FILE *Infile = stdin,*OutFile = stdout;
//FILE *ErrFile = stderr;
#endif
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
cout.tie(nullptr)->sync_with_stdio(false);
int n;
cin>>n;
int cnt = 0,ans = 0;
for(int i = 1,x;i <= n; ++i){
cin>>x;
if(!cnt) cnt = 1,ans = x;
else{
if(ans == x) ++cnt;
else --cnt;
}
}
cout<<ans<<'\n';
}
T2 序列
二分做法 主要是线段树狂WA不止
暴力就是枚举子序列,可以做到\(O(n^2)\)
正解:
先用两个数组\(l_i\)表示\(a_i\)上一次出现的位置,\(r_i\)表示\(a_i\)下一次出现的位置,初值\(l\)为0,\(r\)为inf。
这样做有一个好处,只要满足\(l_i<L \&\& R < r_i\),那么该序列就合法。那么就递归解决\([L,i-1]\)和\([i+1,R]\)
枚举i时从两边找时间最少。
单次时间复杂度\(O(n\log n)\)
点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
using ll=long long;using ull=unsigned long long;
#ifdef LOCAL
FILE *InFile = infile("in.in"),*OutFile = outfile("out.out");
// FILE *ErrFile=errfile("err.err");
#else
FILE *Infile = stdin,*OutFile = stdout;
//FILE *ErrFile = stderr;
#endif
const int N = 2e5 + 10;
int n,T,a[N],l[N],r[N];
bool solve(int L,int R){
if(L >= R) return true;
int xl = L,xr = R;
while(xl < xr){
xl++;
if(l[xl] < L && R < r[xl]) return solve(L,xl-1)&&solve(xl+1,R);
xr--;
if(l[xr] < L && R < r[xr]) return solve(L,xr-1)&&solve(xr+1,R);
}
return false;
}
unordered_map<int,int> mp;
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
cout.tie(nullptr)->sync_with_stdio(false);
cin>>T;
while(T--){
unordered_map<int,int>().swap(mp);
cin>>n;
for(int i = 1;i <= n; ++i) cin>>a[i];
for(int i = 1;i <= n; ++i) l[i] = 0,r[i] = 0x3f3f3f3f;
for(int i = 1;i <= n; ++i){
if(mp[a[i]]){
l[i] = mp[a[i]];
r[mp[a[i]]] = i;
}
mp[a[i]] = i;
}
cout<<(solve(1,n)?"non-boring\n":"boring\n");
}
}
T3 Legacy
线段树优化建图裸题。
点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
using ll=long long;using ull=unsigned long long;
#ifdef LOCAL
FILE *InFile = infile("in.in"),*OutFile = outfile("out.out");
// FILE *ErrFile=errfile("err.err");
#else
FILE *Infile = stdin,*OutFile = stdout;
//FILE *ErrFile = stderr;
#endif
const int N = 1e6 + 10;
struct EDGE{int to,next,w;}edge[N<<1];
int head[N],cnt;
auto add = [](int u,int v,int w) -> void {edge[++cnt] = {v,head[u],w};head[u] = cnt;};
int t1[N<<2],t2[N<<2],tot;
void build(int k,int l,int r){
if(l == r){t1[k] = t2[k] = l;return;}
int mid = (l+r)>>1;
build(k<<1,l,mid);build(k<<1|1,mid+1,r);
t2[k] = ++tot;t1[k] = ++tot;
add(t2[k<<1],t2[k],0);
add(t2[k<<1|1],t2[k],0);
add(t1[k],t1[k<<1],0);
add(t1[k],t1[k<<1|1],0);
}
void updateIn(int k,int l,int r,int L,int R,int u,int w){
if(L <= l && r <= R)return add(u,t1[k],w);
int mid = (l+r)>>1;
if(L <= mid) updateIn(k<<1,l,mid,L,R,u,w);
if(R > mid) updateIn(k<<1|1,mid+1,r,L,R,u,w);
}
void updateOut(int k,int l,int r,int L,int R,int u,int w){
if(L <= l && r <= R) return add(t2[k],u,w);
int mid = (l+r)>>1;
if(L <= mid) updateOut(k<<1,l,mid,L,R,u,w);
if(R > mid) updateOut(k<<1|1,mid+1,r,L,R,u,w);
}
#define pli pair<ll,int>
#define mk make_pair
ll dist[N];
bitset<N> vis;
void dijkstra(int s){
memset(dist,0x3f,sizeof dist);
vis.reset();
dist[s] = 0;
priority_queue<pli,vector<pli>,greater<pli> > q;
q.push(mk(0,s));
while(q.size()){
int x = q.top().second;q.pop();
if(vis[x]) continue;
vis[x] = true;
for(int i = head[x]; i;i = edge[i].next){
int y = edge[i].to;
if(dist[y] > dist[x] + edge[i].w){
dist[y] = dist[x] + edge[i].w;
q.push(mk(dist[y],y));
}
}
}
}
int n,q,s;
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
cout.tie(nullptr)->sync_with_stdio(false);
cin>>n>>q>>s;
tot = n;
build(1,1,n);
for(int i = 1;i <= q; ++i){
int op;cin>>op;
if(op == 1){
int u,v,w;
cin>>u>>v>>w;
add(u,v,w);
}
if(op == 2){
int u,l,r,w;
cin>>u>>l>>r>>w;
updateIn(1,1,n,l,r,u,w);
}
if(op == 3){
int v,l,r,w;
cin>>v>>l>>r>>w;
updateOut(1,1,n,l,r,v,w);
}
}
dijkstra(s);
for(int i = 1;i <= n; ++i){
cout<<(dist[i] == dist[0]?-1:dist[i])<<' ';
}
}
T4 DP搬运工1
暴力就是直接枚举。
状压可以多拿一点。
正解是预设性dp
\(f_{i,j,k}\)表示填到位置\(i\),还有\(j\)个位置可以填,当前和为\(k\)的方案数。
点此查看代码
#include<bits/stdc++.h>
#include<bits/extc++.h>
// using namespace __gnu_pbds;
// using namespace __gnu_cxx;
using namespace std;
#define infile(x) freopen(x,"r",stdin)
#define outfile(x) freopen(x,"w",stdout)
#define errfile(x) freopen(x,"w",stderr)
using ll=long long;using ull=unsigned long long;
#ifdef LOCAL
FILE *InFile = infile("in.in"),*OutFile = outfile("out.out");
// FILE *ErrFile=errfile("err.err");
#else
FILE *Infile = stdin,*OutFile = stdout;
//FILE *ErrFile = stderr;
#endif
const int N = 60,mod = 998244353;
ll f[N][N][N*N],n,k;
signed main(){
cin.tie(nullptr)->sync_with_stdio(false);
cout.tie(nullptr)->sync_with_stdio(false);
cin>>n>>k;
f[1][0][0] = 1;
for(int i = 2;i <= n; ++i){
for(int j = 0;j <= n - i + 1; ++j){
for(int t = 0;t <= k; ++t){
if(f[i-1][j][t]){
f[i][j+1][t] = (f[i][j+1][t] + f[i-1][j][t]*2)%mod;
f[i][j][t + i] = (f[i][j][t+i] + f[i-1][j][t]*2)%mod;
if(j){
f[i][j+1][t] = (f[i][j+1][t] + f[i-1][j][t] * j) % mod;
f[i][j][t + i] = (f[i][j][t+i] + f[i-1][j][t]*2*j) % mod;
f[i][j-1][t+i+i] = (f[i][j-1][t+i+i] + f[i-1][j][t] * j) % mod;
}
}
}
}
}
ll ans = 0;
for(int i = 0;i <= k; ++i) ans = (ans + f[n][0][i])%mod;
cout<<ans;
}