四川省大学生程序设计大赛
C. Black-White Cubic Lattice
考点:最小费用流
#include<bits/stdc++.h>
using namespace std;
const int N = 10010, M = 200010, inf = 1e9;
typedef long long ll;
int n, m, S, T;
int h[N], e[M], f[M], ne[M], idx;
int q[N], d[N], cur[N];
void add(int a, int b, int c)
{
e[idx] = b, f[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
e[idx] = a, f[idx] = 0, ne[idx] = h[b], h[b] = idx ++ ;
}
bool bfs()
{
int hh = 0, tt = 0;
memset(d, -1, sizeof d);
q[0] = S, d[S] = 0, cur[S] = h[S];
while (hh <= tt)
{
int t = q[hh ++ ];
for (int i = h[t]; ~i; i = ne[i])
{
int ver = e[i];
if (d[ver] == -1 && f[i])
{
d[ver] = d[t] + 1;
cur[ver] = h[ver];
if (ver == T) return true;
q[ ++ tt] = ver;
}
}
}
return false;
}
int find(int u, int limit)
{
if (u == T) return limit;
int flow = 0;
for (int i = cur[u]; ~i && flow < limit; i = ne[i])
{
cur[u] = i;
int ver = e[i];
if (d[ver] == d[u] + 1 && f[i])
{
int t = find(ver, min(f[i], limit - flow));
if (!t) d[ver] = -1;
f[i] -= t, f[i ^ 1] += t, flow += t;
}
}
return flow;
}
ll dinic()
{
int flow;
ll r=0;
while (bfs()) while (flow = find(S, inf)) r += flow;
return r;
}
int main()
{
int N,M,L;
cin>>N>>M>>L;
memset(h, -1, sizeof h);
vector<vector<vector<int>>> c(L,vector<vector<int>>(N,vector<int>(M)));
vector<vector<string>> s(L,vector<string>(N));
S=N*M*L+2,T=S+1;
for(int i=0;i<L;i++){
for(int j=0;j<N;j++){
cin>>s[i][j];
}
}
for(int i=0;i<L;i++){
for(int j=0;j<N;j++){
for(int k=0;k<M;k++){
cin>>c[i][j][k];
if(s[i][j][k]=='W'){
add((i*N+j)*M+k,T,c[i][j][k]);
}else{
add(S,(i*N+j)*M+k,c[i][j][k]);
}
if(i>0){
add((i*N+j)*M+k,((i-1)*N+j)*M+k,inf);
}
if(j>0){
add((i*N+j)*M+k,(i*N+j-1)*M+k,inf);
}
if(k>0){
add((i*N+j)*M+k,(i*N+j)*M+k-1,inf);
}
}
}
}
add(S,0,inf),add(N*M*L-1,T,inf);
printf("%lld\n", dinic());
return 0;
}
G. Function Query
考点:字典树
#include<bits/stdc++.h>
using namespace std;
//#define int long long
#define x first
#define y second
const int N=9e6+10,inf=0x3f3f3f3f;
int tr[N][2],idx=1,f[N];
void add(int x,int id){
int p=1;
for(int i=30;i>=0;i--){
int t=x>>i&1;
if(tr[p][t]==0){
tr[p][t]=++idx;
}
p=tr[p][t];
f[p]=min(f[p],id);
}
}
int query(int a,int b){
int p=1,ans1=inf,ans2=inf;
for(int i=30;i>=0;i--){
int d=a>>i&1;
int e=b>>i&1;
if(e){
//求x^a小于b的最小下标,让x的第i位^a的第i位为0就小于b了,即x的第i位等于a的第i位
ans1=min(ans1,f[tr[p][d]]);
}else{
//求x^a大于b的最小下标
ans2=min(ans2,f[tr[p][d^1]]);
}
//前面x的位数取值异或a等于b。a^x=b => a^b=x
//p从零开始的话,如果节点没有赋值,则为0,又从根节点开始,这样不行,所以根节点赋值为1才行
p=tr[p][d^e];
}
ans1=min(ans1,f[p]);//这里再加上等于的情况
ans2=min(ans2,f[p]);
if(ans1==inf||ans2==inf) return -1;
//如果所有的数都是a^x=b,则下标是第一个即0,这时候答案是1
return max(1,max(ans1,ans2));//因为下标从0开始的,所以算是自动-1了max-1
}
void solve(){
ios::sync_with_stdio(false);//记得关流,不然会超时,1e5次方的时候
cin.tie(0);cout.tie(0);
int n,q;cin>>n>>q;
vector<int> x(n);
memset(f,0x3f,sizeof f);
memset(tr,0,sizeof tr);
idx=1;
for(int i=0;i<n;i++){
cin>>x[i];
add(x[i],i);
}
while(q--){
int a,b;cin>>a>>b;
cout<<query(a,b)<<endl;
}
}
signed main(){
int T=1;
// cin>>T;
while(T--){
solve();
}
return 0;
}
I. Container Scheduling
考点:构造
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
typedef long long ll;
void solve(){
int n,l,h;
cin>>n>>l>>h;
vector<int> x(n,-1),y(n,-1),a(n),b(n);//x,y存放每个放置矩形的左下角点坐标,a,b表示矩形的长度
set<int> cx{0},cy{0};//表示能存放在x,y轴上的位置
for(int i=0;i<n;i++){
cin>>a[i]>>b[i];
for(auto vx:cx){
for(auto vy:cy){
int ok=1;
if(vx+a[i]>l||vy+b[i]>h){
continue;
}
for(int j=0;j<i;j++){
//只需要错开即可不重叠,!后表示有重叠部分
if(!(x[j]==-1||(vx>=x[j]+a[j]||vx+a[i]<=x[j])||(vy>=y[j]+b[j]||vy+b[i]<=y[j]))){
ok=0;
break;
}
}
if(ok){
x[i]=vx;
y[i]=vy;
cx.insert(vx+a[i]);
cy.insert(vy+b[i]);
break;
}
}
if(x[i]!=-1){
break;
}
}
if(x[i]==-1){
cout<<"-1"<<endl;
}else{
cout<<x[i]<<" "<<y[i]<<endl;
}
}
}
signed main(){
int T=1;
// cin>>T;
while(T--){
solve();
}
return 0;
}
J. Roman Numerals
考点:DP
#include<bits/stdc++.h>
using namespace std;
const int inf=1e9;
const int V[]={0,1,2,3,4,5,6,7,8,9,1,5,10,50,100,500,1000};
typedef long long ll;
void solve(){
string s;
cin>>s;
array<int,17> c;
for(int i=0;i<17;i++){
cin>>c[i];
}
vector<int> dp(112,inf);
ll cur=0;
for(auto _:s){
int d=_-'0';
cur=cur*10+d;
vector<int> ndp(112,inf);
for(int i=0;i<112;i++){
for(int j=0;j<17;j++){
int r=i*10+d-V[j];
if(0<=r&&r<=111){
ndp[r]=min(ndp[r],dp[i]+c[j]);
}
}
}
for(int j=0;j<17;j++){
ll r=cur-V[j];
if(0<=r&&r<=111){
ndp[r]=min(ndp[r],c[j]);
}
}
swap(dp,ndp);
}
cout<<dp[0]<<"\n";
}
signed main(){
int T=1;
cin>>T;
while(T--){
solve();
}
return 0;
}
K. Element Reaction
考点:高维前缀和(FMT)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr),cout.tie(0);
int n,m;//m种元素,n个元素序列
cin>>m>>n;
vector<vector<int>> a(m, vector<int>(m));
// vector<vector<int>> a(m);
// for(int i=0;i<m;i++){
// a[i].resize(m);
// }
for(int i=0;i<m;i++){
for(int j=0;j<m;j++){
cin>>a[i][j];
}
}
string s;
cin>>s;
vector<pair<int,int> > nxt(m);
for(int i=0;i<m;i++){
nxt[i]={i,n};
}
vector<ll> f(1<<m);
for(int i=n-1;i>=0;i--){
int mask=0;
int x=s[i]-'a';
for(int j=0;j<m;j++){
if(nxt[j].second==n){
break;
}
int y=nxt[j].first;
f[mask]+=a[x][y];
f[mask|1<<x]-=a[x][y];
f[mask|1<<y]-=a[x][y];
f[mask|1<<x|1<<y]+=a[x][y];
if(nxt[j].first==x){
break;
}
mask|=1<<y;
}
int j=0;
while(nxt[j].first!=x){
j++;
}
nxt.erase(nxt.begin()+j);
nxt.insert(nxt.begin(),make_pair(x,i));
}
for(int i=1;i<(1<<m);i*=2){
for(int j=0;j<(1<<m);j+=2*i){
for(int k=0;k<i;k++){
f[i+j+k]+=f[j+k];
}
}
}
for(int i=0;i<(1<<m);i++){
cout<<f[i]<<" \n"[i==(1<<m)-1];
}
}