2019 hdu 多校第一场 6/13

吐槽一下最近讲课太累了都没啥时间补题了,哎,队友也不补题

A

f i , j , k , l f_{i,j,k,l} fi,j,k,l表示四种颜色的最后的位置排序之后的结果,然后滚动掉最后一维就好了

/* ***********************************************
Author        :BPM136
Created Time  :7/24/2019 8:07:39 PM
File Name     :1001.cpp
************************************************ */

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define USE_CIN_COUT ios::sync_with_stdio(0)

using namespace std;

typedef long long ll;
typedef double db;
typedef long double ld;
typedef unsigned int ui;
typedef unsigned long long ull;
typedef pair<int, int> pii;

int const N = 105;
int const mod = 998244353;

inline void update(int& a, int b) {
	a += b;
	if (a >= mod)
		a -= mod;
}

vector<pii> t[N];
int f[N][N][N][2];

int main() {
	int T;
	cin >> T;
	while (T--) {
		int n, m;
		cin >> n >> m;
		for (int i = 0; i <= n; ++i) {
			t[i].clear();
			t[i].emplace_back(i, 1);
		}
		for (int i = 0; i < m; ++i) {
			int x, y, c;
			cin >> x >> y >> c;
			t[y].emplace_back(x, c);
		}
		memset(f, 0, sizeof(f));
		f[0][0][0][0] = 1;
		for (int p = 1; p <= n; ++p) {
			int now = p & 1;
			for (int i = 0; i <= p; ++i) 
				for (int j = i; j <= p; ++j)
					for (int k = j; k <= p; ++k) 
						f[i][j][k][now] = 0;
			for (int i = 0; i <= p; ++i) 
				for (int j = i; j <= p; ++j)
					for (int k = j; k <= p; ++k) {
						update(f[j][k][p - 1][now], f[i][j][k][now ^ 1]);
						update(f[i][k][p - 1][now], f[i][j][k][now ^ 1]);
						update(f[i][j][p - 1][now], f[i][j][k][now ^ 1]);
						update(f[i][j][k][now], f[i][j][k][now ^ 1]);
					}
			for (int i = 0; i <= p; ++i)
				for (int j = i; j <= p; ++j)
					for (int k = j; k <= p; ++k)
						for (auto const& lim : t[p]) {
							auto l = lim.first, sum = lim.second;
							auto s = (i >= l) + (j >= l) + (k >= l) + 1;
							if (s != sum)
								f[i][j][k][now] = 0;
						}
		}
		int ans = 0;
		for (int i = 0; i <= n; ++i)
			for (int j = i; j <= n; ++j)
				for (int k = j; k <= n; ++k)
					update(ans, f[i][j][k][n & 1]);
		cout << ans << '\n';
	}
    return 0;
}

B

优秀的线性基,因为一个位置的前缀的线性基最多只有本质K种而已,然后就维护一下线性基每个位置最后的数的位置就好了。

/* ***********************************************
Author        :BPM136
Created Time  :7/24/2019 9:21:12 PM
File Name     :1002.cpp
************************************************ */

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define USE_CIN_COUT ios::sync_with_stdio(0)

using namespace std;

typedef long long ll;
typedef double db;
typedef long double ld;
typedef unsigned int ui;
typedef unsigned long long ull;

int const N = 1000005;

int f[N][32], pos[N][32];
int n, m;

void add(int k, int val) {
	for (int i = 30; i >= 0; --i) {
		f[k][i] = f[k - 1][i];
		pos[k][i] = pos[k - 1][i];
	}
	int now = k;
	for (int i = 30; i >= 0; --i) 
		if (val & (1 << i)) {
			if (f[now][i] == 0) {
				f[now][i] = val;
				pos[now][i] = k;
				return;
			} else {
				if (k > pos[now][i]) {
					swap(pos[now][i], k);
					swap(f[now][i], val);
				}
				val ^= f[now][i];
			}
		}
}

int getAns(int l, int r) {
	int ret = 0;
	for (int i = 30; i >= 0; --i)
		if (pos[r][i] >= l && (ret ^ f[r][i]) > ret) 
			ret ^= f[r][i];
	return ret;
}

int main() {
	USE_CIN_COUT;
	int T;
	cin >> T;
	while (T--) {
		cin >> n >> m;
		for (int i = 1; i <= n; ++i) {
			int x;
			cin >> x;
			add(i, x);
		}
		int lastans = 0;
		while (m--) {
			int op;
			cin >> op;
			if (op == 0) {
				int l, r;
				cin >> l >> r;
				l = (l ^ lastans) % n + 1;
				r = (r ^ lastans) % n + 1;
				if (l > r)
					swap(l, r);
				cout << (lastans = getAns(l, r)) << '\n';
			} else {
				int x;
				cin >> x;
				x ^= lastans;
				add(++n, x);
			}
		}
	}
    return 0;
}

D

写了个并查集每次往前合并,然后set暴力修改碰撞时间的东西,然而可以二分答案,还可以线性求答案(因为一定是某车卡住了最后一辆,然后就可以求出如果这辆车是卡住的那个,那么时间是多少,最后取个max就行)

/* ***********************************************
Author        :BPM136
Created Time  :7/22/2019 3:55:25 PM
File Name     :1004.cpp
************************************************ */

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define USE_CIN_COUT ios::sync_with_stdio(0)

using namespace std;

typedef long long ll;
typedef long double db;
typedef unsigned int ui;
typedef unsigned long long ull;

int const N = 200005;
db const inf = 1e30;

int len[N], s[N], v[N];
int uns[N], unslen[N], unsmin[N];
db unss[N], unst[N];
db chu;
db tim[N];

int unsFind(int x) {
	if (uns[x] == x)
		return x;
	return uns[x] = unsFind(uns[x]);
}

db calc(int x, int y) {
	int dx = unsFind(x), dy = unsFind(y);
	if (dx == dy)
		return 0;
	if (v[dx] > v[dy]) {
		db dis = 1.0 * unss[dy] + v[dy] * unst[dy] + 1.0 * unslen[dy] - unss[dx] - v[dx] * unst[dx];
		// cerr << "d : " << dis << ' ' << v[dy] - v[dx] << '\n';
		return dis / (1.0 * (v[dy] - v[dx]));
	}
	return inf;
}

db ans = 0;

bool chk(db ti) {
	int dx = unsFind(0);
	if (1.0 * unss[dx] + unslen[dx] - chu <= v[dx] * (ti - unst[dx])) {
		ans = 1.0 * unss[dx] + unslen[dx] - chu + v[dx] * unst[dx];
		ans = ans / v[dx];
		return 1;
	}
	return 0;
}

struct node {
	db time;
	int i;
	bool operator < (node const& oth) const {
		if (time == oth.time)
			return i > oth.i;
		return time < oth.time;
	}
};

int main() {
	USE_CIN_COUT;
	int n;
	while (cin >> n) {
		for (int i = 0; i <= n; ++i)
			cin >> len[i];
		for (int i = 0; i <= n; ++i)
			cin >> s[i];
		for (int i = 0; i <= n; ++i)
			cin >> v[i];
		chu = len[0];
		for (int i = 0; i <= n; ++i) {
			uns[i] = i;
			unslen[i] = len[i];
			unsmin[i] = i;
			unss[i] = s[i];
			unst[i] = 0;
		}
		auto S = set<node>();
		for (int i = 0; i < n; ++i) {
			db t = calc(i, i + 1);
			tim[i] = t;
			S.insert(node{ t, i });
			// cerr << t << ' ';
		}
		// cerr << '\n';
		node infnode = node{ inf, 0 }, it;
		for (; ; ) {
			it = infnode;
			if (SZ(S)) {
				it = *S.begin();
				S.erase(S.begin());
			}
			// cerr << it.time << ' ' << it.i << '\n';
			if (chk(it.time)) {
				cout << fixed << setprecision(10) << ans << '\n';
				break;
			}
			auto pos = it.i;
			auto dx = unsFind(pos), dy = unsFind(pos + 1);
			uns[dx] = dy;
			unslen[dy] += unslen[dx];
			unsmin[dy] = unsmin[dx];
			unss[dy] = unss[dy] - (it.time - unst[dy]) * v[uns[dy]];
			unst[dy] = it.time;
			int pre = unsmin[dy] - 1;
			if (pre >= 0) {
				double ti = calc(pre, dy);
				auto iter = S.find(node{ tim[pre], pre });
				if (iter != S.end())
					S.erase(iter);
				tim[pre] = ti;
				S.insert(node{ tim[pre], pre });
			}
		}
	}
    return 0;
}

E

最短路DAG上最小流即可

/* ***********************************************
Author        :BPM136
Created Time  :7/22/2019 2:48:20 PM
File Name     :1005.cpp
************************************************ */

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define USE_CIN_COUT ios::sync_with_stdio(0)

using namespace std;

typedef long long ll;
typedef double db;
typedef long double ld;
typedef unsigned int ui;
typedef unsigned long long ull;
typedef pair<ll, int> pli;

int const N = 10005;
int const M = 40005;
ll const inf = 1e15;

struct ISAP {
	struct Edge {
		int y,next;
		ll f;
	}e[M];
	int last[N],ne;

	int d[N],cur[N],pre[N],num[N];
	int S,T,nv;

	void init(int _n) {
		S=_n+1; T=_n+2;
		nv=T+1;
		ne=0;
		memset(last,-1,sizeof(last));
	}

	void add(int x,int y,ll f) {
		e[ne].y=y; e[ne].f=f; e[ne].next=last[x]; last[x]=ne; ne++;
	}
	void link(int x,int y,ll f) {
		add(x,y,f);
		add(y,x,0);
	}

	void rev_bfs() {
		memset(num,0,sizeof(num));
		memset(d,-1,sizeof(d));
		d[T]=0;
		num[0]=1;
		queue<int> Q;
		while(!Q.empty()) Q.pop();
		Q.push(T);
		while(!Q.empty()) {
			int x=Q.front(); Q.pop();
			for(int i=last[x];~i;i=e[i].next) {
				int y=e[i].y;
				if(~d[y]) continue;
				d[y]=d[x]+1;
				num[d[y]]++;
				Q.push(y);
			}
		}
	}

	ll solve() {
		memset(pre,0,sizeof(pre));
		memcpy(cur,last,sizeof(cur));
		rev_bfs();
		if(d[S]==-1) return 0; ///不联通
		ll ret=0;
		int u=pre[S]=S,i;

		while(d[T]<nv) {
			if(u==T) {
				ll f=inf;
				int neck = 0;
				for(i=S;i!=T;i=e[cur[i]].y) {
					if(f>e[cur[i]].f) {
						f=e[cur[i]].f;
						neck=i;
					}
				}
				for(i=S;i!=T;i=e[cur[i]].y) {
					e[cur[i]].f-=f;
					e[cur[i]^1].f+=f;
				}
				ret+=f;
				u=neck;
			}
			for(i=cur[u];~i;i=e[i].next) if(d[e[i].y]+1==d[u] && e[i].f) break;
			if(~i) {
				cur[u]=i;
				pre[e[i].y]=u;
				u=e[i].y;
			} else {
				if(0== (--num[d[u]])) break;
				int mind=nv;
				for(i=last[u];~i;i=e[i].next) {
					if(e[i].f && mind>d[e[i].y]) {
						cur[u]=i;
						mind=d[e[i].y];
					}
				}
				d[u]=mind+1;
				num[d[u]]++;
				u=pre[u];
			}
		}
		return ret;
	}
}isap;

struct edge {
	int y, c;
	int next;
}e[M << 1];
int last[N], ne;
int n, m;

void addedge(int x, int y, int c) {
	e[++ne].y = y;
	e[ne].c = c;
	e[ne].next = last[x];
	last[x] = ne;
}

void dijstra(int S, std::vector<ll>& dis) {
	std::priority_queue<pli, std::vector<pli>, std::greater<pli>> Q;
	dis.resize(n);
	std::vector<bool> vis;
	vis.resize(n);
	for(int i = 0; i <= n; ++i)
		dis[i] = inf, vis[i] = 0;
	dis[S] = 0;
	Q.push(std::make_pair(0ll, S));
	while(Q.empty() == 0) {
		pli now = Q.top();
		Q.pop();
		if(vis[now.second]) continue;
		vis[now.second] = 1;
		for(int i = last[now.second]; i != 0; i = e[i].next) {
			if(dis[e[i].y] > dis[now.second] + e[i].c) {
				dis[e[i].y] = dis[now.second] + e[i].c;
				Q.push(std::make_pair(dis[e[i].y], e[i].y));
			}
		}
	}
}

int main() {
	USE_CIN_COUT;
	int T;
	cin >> T;
	while (T--) {
		cin >> n >> m;
		isap.init(n);
		for (int i = 1; i <= n; ++i)
			last[i] = 0;
		ne = 0;
		for (int i = 1; i <= m; ++i) {
			int x, y, c;
			cin >> x >> y >> c;
			addedge(x, y, c);
		}
		auto dis = vector<ll>(n + 1);
		dijstra(1, dis);~~~
		for (int i = 1; i <= n; ++i)
			for (int j = last[i]; j; j = e[j].next) 
				if (dis[i] + e[j].c == dis[e[j].y]) 
					isap.link(i, e[j].y, e[j].c);
		isap.link(isap.S, 1, inf);
		isap.link(n, isap.T, inf);
		cout << isap.solve() << '\n';
	}
    return 0;
}

F

G

H

I

大力贪心即可,每次判断后面我们能不能同时满足限制即可

/* ***********************************************
Author        :BPM136
Created Time  :7/22/2019 7:23:30 PM
File Name     :1009.cpp
************************************************ */

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(),(x).end()
#define USE_CIN_COUT ios::sync_with_stdio(0)

using namespace std;

typedef long long ll;
typedef double db;
typedef long double ld;
typedef unsigned int ui;
typedef unsigned long long ull;

int const N = 100005;

int l[27], r[27];
queue<int> tab[26];
int suf[N][26];
int now[26];
string s;
int n, m;
char ans[N];

bool chk(int p, int ch) {
	int sum = 0, sum2 = 0;
	// cerr << p << ' ' << ch << '\n';
	for (int i = 0; i < 26; ++i) {
		if (min(suf[p][i], n - m - 1) + now[i] + (ch == i) < l[i])
			return 0;
		sum += min(suf[p][i], r[i] - now[i] - (ch == i));
		if (now[i] + (ch == i) < l[i])
			sum2 += l[i] - now[i] - (ch == i);
	}
	// cerr << " ? " << sum << ' ' << sum2 << '\n';
	if (sum < n - m - 1 || sum2 > n - m - 1)
		return 0;
	return 1;
}

int main() {
	freopen("02", "r", stdin);
	freopen("out.txt", "w", stdout);
	while (cin >> s >> n) {
		m = 0;
		for (int i = 0; i < 26; ++i) {
			cin >> l[i] >> r[i];
			while (tab[i].empty() == 0)
				tab[i].pop();
		}
		for (int i = 0; i < SZ(s); ++i) 
			tab[s[i] - 'a'].push(i);
		fill(suf[SZ(s)], suf[SZ(s)] + 26, 0);
		for (int i = SZ(s) - 1; i >= 0; --i) {
			for (int j = 0; j < 26; ++j)
				suf[i][j] = suf[i + 1][j];
			suf[i][s[i] - 'a']++;
		}
		fill(now, now + 26, 0);
		int p = -1;
		for (int i = 1; i <= n; ++i) {
			for (int j = 0; j < 26; ++j) {
				while (tab[j].empty() == 0 && tab[j].front() <= p)
					tab[j].pop();
				if (tab[j].empty() || now[j] == r[j])
					continue;
				if (chk(tab[j].front(), j)) {
					now[j]++;
					ans[++m] = j + 'a';
					p = tab[j].front();
					// cerr << char(j + 'a') << ' ' << tab[j].front() << '\n';
					break;
				}
			}
			if (i != m)
				break;
		}
		if (m < n) 
			cout << -1 << '\n';
		else {
			ans[++m] = '\0';
			cout << ans + 1 << '\n';
		}
	}
    return 0;
}

J

K

L

M

就是判断两个凸包是否有交即可(点在边上也算相交)

你可能感兴趣的:(2019多校,ACM补题)