2018-2019 Russia Open High School Programming Contest 9/13

A

Solved: 00:10 zkp

#include 
using namespace std;
long long a[200010],b[200010];
int main() {
	int n,m;
	long long ans=0,sum,t;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		sum=0;
		cin>>m;
		for(int j=0;j<m;j++)scanf("%lli",&t),sum=max(sum,t);
		a[i]=sum,b[i]=m;
	}
	sum=0;
	for(int i=0;i<n;i++)sum=max(sum,a[i]);
	for(int i=0;i<n;i++)ans+=(sum-a[i])*b[i];
	cout<<ans<<endl;
	return 0;
}

B

傻逼签到xD

#include 

using namespace std;

#define SZ(x) ((int)(x).size())

vector<string> a;
vector<pair<string, string> > t;
map<string, string> smap;

string const BEGIN = "\\begin{thebibliography}{99}";
string const END = "\\end{thebibliography}";

vector<string> solve(string s) {
	vector<string> ret;
	for (int i = 0; i + 6 < SZ(s); ++i)
		if (s[i] == '\\' && s.substr(i, 6) == "\\cite{") {
			int num = 0, canf = 0;
			for (int j = i + 6; j < SZ(s); ++j) 
				if (s[j] == '}') {
					canf = 1;
					break;
				} else
					++num;
			if (canf) {
				ret.push_back(s.substr(i + 6, num));
				i = i + 6 + num;
			} else
				i = SZ(s);
		}
	return ret;
}

int main() {
	string str;
	while (str != BEGIN) {
		getline(cin, str);
		auto vt = solve(str);
		for (auto& s : vt) 
			a.push_back(s);
	}

	while (getline(cin, str)) {
		if (str == END)
			break;
		int num = 0;
		for (int j = 9; j < SZ(str); ++j)
			if (str[j] == '}') 
				break;
			else
				++num;
		string st = str.substr(9, num);
		t.push_back(make_pair(st, str));
		smap[st] = str;
	}

	assert(SZ(a) == SZ(t));
	bool fans = 1;
	for (int i = 0; i < SZ(t); ++i)
		if (t[i].first != a[i]) {
			fans = 0;
			break;
		}
	if (fans) 
		puts("Correct");
	else {
		puts("Incorrect");
		cout << BEGIN << '\n';
		for (auto& s : a) 
			cout << smap[s] << '\n';
		cout << END << '\n';
	}
}

C

Unsolved

D

Solved: 00:32 zkp
构造好快啊

#include 
using namespace std;
vector<int>a[100010];
int ans[100010];
int main()
{
	int n,m,x,y;
	cin>>n>>m;
	for(int i=0;i<m;i++)
	{
		cin>>x>>y;
		a[x].push_back(y);
		a[y].push_back(x);
	}
	if(n==1)
	{
		cout<<"NO"<<endl;
		return 0;
	}
	x=-1,y=-1;
	for(int i=1;i<=n;i++)
	{
		a[i].push_back(i);
		sort(a[i].begin(),a[i].end());
		if(a[i][0]!=1)x=i,y=1;
		for(int j=1;j<a[i].size();j++)if(a[i][j]!=a[i][j-1]+1)x=i,y=a[i][j-1]+1;
	}
	if(x==-1)
	{
		cout<<"NO"<<endl;
		return 0;
	}
	int now=3;
	cout<<"YES\n";
	for(int i=1;i<=n;i++)if(i!=x&&i!=y)ans[i]=now++;
	ans[x]=1,ans[y]=2;
	for(int i=1;i<=n;i++)cout<<ans[i]<<" ";
	cout<<endl;
	ans[y]=1;
	for(int i=1;i<=n;i++)cout<<ans[i]<<" ";
	cout<<endl;
	return 0;
}

E

Solved: 02:44 zkp
一个点到另一个点的步数不会超过10步的样子?

#include 
using namespace std;
int mp[10][10];
int dx[]={1,1,-1,-1,2,2,-2,-2};
int dy[]={2,-2,-2,2,1,-1,1,-1};
int px[10][10],py[10][10];
vector<int>ans[4];
void prt(int x,int y,int rx,int ry)
{
	if(x==rx&&y==ry)return;
	if(mp[px[rx][ry]][py[rx][ry]])prt(x,y,px[rx][ry],py[rx][ry]);
	ans[0].push_back(rx),ans[1].push_back(ry);
	ans[2].push_back(px[rx][ry]),ans[3].push_back(py[rx][ry]);
	if(!mp[px[rx][ry]][py[rx][ry]])prt(x,y,px[rx][ry],py[rx][ry]);
}
void BFS(int x,int y)
{
	if(mp[x][y]==1)
	{
		mp[x][y]=-1;
		return;
	}
	for(int i=0;i<10;i++)for(int j=0;j<10;j++)px[i][j]=py[i][j]=0;
	px[x][y]=-1;
	queue<pair<int,int> >q;
	q.push(make_pair(x,y));
	int nx,ny,gx=10,gy=-1,ex,ey;
	while(!q.empty())
	{
		nx=q.front().first;
		ny=q.front().second;
		q.pop();
		for(int i=0;i<8;i++)
		{
			ex=nx+dx[i];ey=ny+dy[i];
			if(ex>8||ex<1||ey>8||ey<1)continue;
			if(px[ex][ey])continue;
			px[ex][ey]=nx;
			py[ex][ey]=ny;
			if(mp[ex][ey]==1&&(ex<gx||(ex==gx&&ey<gy)))gx=ex,gy=ey;
			q.push(make_pair(ex,ey));
		}
	}
	prt(x,y,gx,gy);
	mp[gx][gy]=0,mp[x][y]=-1;
} 
int main()
{
	int n;
	cin>>n;
	string s;
	for(int i=0;i<n;i++)cin>>s,mp[s[0]-'a'+1][s[1]-'0']=1;
	for(int i=0;i<n;i++)
	{
		BFS(i%8+1,i/8+1);
	}
	cout<<ans[1].size()<<endl;
	for(int i=0;i<ans[1].size();i++)
	{
		cout<<char(ans[0][i]+'a'-1)<<ans[1][i]<<"-";
		cout<<char(ans[2][i]+'a'-1)<<ans[3][i]<<"\n";
	} 
	return 0;
}

F

Unsolved

G

Unsolved

H

Unsolved

I

Solved: 01:30 zkp
-8太dirt了吧,以后要让zkp控制好罚时才行
单调栈

#include 
using namespace std;
unsigned int b[10000010];
long long a[10000010];
long long st[10000010];
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		long long n,l,r,x,y,z,now=9223372036854775807ll,ans=9223372036854775807ll,sz=0;
		cin>>n>>l>>r>>x>>y>>z>>b[1]>>b[2];
		for(int i=3;i<=n;i++)b[i]=(b[i-2]*x+b[i-1]*y+z);
		for(int i=1;i<=n;i++)a[i]=b[i]%(r-l+1)+l;
		for(int i=1;i<=n;i++)
		{
			if(a[i]>=0)
			{
				if(a[i]>now)ans=min(ans,a[i]*now);
				now=min(a[i],now);
				continue;
			}
			now=min(now,a[i]);
			while(sz!=0&&st[sz]<a[i])ans=min(ans,st[sz]*a[i]),sz--;
			st[++sz]=a[i];
		}
		if(ans==9223372036854775807ll)cout<<"IMPOSSIBLE\n";
		else cout<<ans<<endl;
	}
	return 0;
}

J

Solved: 04:27 BPM136
询问两个串的前缀连接成的本质不同的字符串有多少个
如果两个连接相同,那么第一个串的某个位置结束的后缀和第二个串某个位置i的长度为i-nxt[i]长度的前缀完全相同。
那么对于第二个串kmp
第一个串SAM,来统计那个前缀有多少个
然后对于每个i-nxt[i]的前缀在SAM上跑就可以统计答案了

#include 

using namespace std;

#define SZ(x) ((int)(x).size())

using ll = long long;

const int N = 200005;

int ch[N][26], sam_sz[N], par[N], mx[N];
int v[N];
int sam_cnt, sam_last;

void SAM_init() {
	sam_cnt = sam_last = 1;
	memset(ch, 0, sizeof(ch));
	memset(par, 0, sizeof(par));
	memset(mx, 0, sizeof(mx));
	memset(sam_sz, 0, sizeof(sam_sz));
}

int SAM_extend(int x) {
	if(ch[sam_last][x]) {
		int p = sam_last, q = ch[p][x];
		if(mx[q] == mx[p] + 1) return sam_last = q, q;
		int nq = ++sam_cnt; 
		mx[nq] = mx[p] + 1;
		memcpy(ch[nq], ch[q], sizeof(ch[q]));
		par[nq] = par[q];
		par[q] = nq;
		for(; ch[p][x] == q; p = par[p]) ch[p][x] = nq;
		return sam_last = nq, nq;
	}
	int p, q, np, nq;
	p = sam_last;
	sam_last = np = ++sam_cnt;
	mx[np] = mx[p] + 1;
	sam_sz[np] = 1;
	for(; p && !ch[p][x]; p = par[p]) ch[p][x] = np;
	if(!p) par[np] = 1;
	else {
		q = ch[p][x];
		if(mx[q] == mx[p] + 1) par[np] = q;
		else {
			nq = ++sam_cnt;
			mx[nq] = mx[p] + 1;
			memcpy(ch[nq], ch[q], sizeof(ch[q]));
			par[nq] = par[q];
			par[q] = par[np] = nq;
			for(; ch[p][x] == q; p = par[p]) ch[p][x] = nq;
		}
	}
	return sam_last;
}

int samt[N];
void SAM_topoSort() {
	static int b[N];
	memset(b, 0, sizeof(b));
	memset(samt, 0, sizeof(samt));
	for(int i = 1; i <= sam_cnt; i++) b[mx[i]]++;
	for(int i = 1; i <= sam_cnt; i++) b[i] += b[i - 1];
	for(int i = sam_cnt; i >= 1; i--) samt[b[mx[i]]--] = i;
	for(int i = sam_cnt; i >= 1; i--) sam_sz[par[samt[i]]] += sam_sz[samt[i]];
	for(int i = sam_cnt; i >= 1; --i) 
		v[par[samt[i]]] += v[samt[i]];
}

int nxt[N];
int num[N];

void KMP(string& s) {
	nxt[0] = 0;
	for (int i = 1, j = 0, m = (int)s.size(); i < m; ++i) {
		while (j && s[i] != s[j])
			j = nxt[j - 1];
		if (s[i] == s[j]) 
			++j;
		nxt[i] = j;
	}
}

int main() {
	string s1, s2;
	cin >> s1 >> s2;
	SAM_init();
	for (int i = 1; i < SZ(s1); ++i)
		SAM_extend(s1[i] - 'a');
	int p = 1;
	for (int i = 1; i < SZ(s1); ++i) {
		p = ch[p][s1[i] - 'a'];
		v[p] = 1;
	}
	SAM_topoSort();
	v[0] = 0;
	KMP(s2);
	for (int i = 0; i < SZ(s2); ++i) 
		if (nxt[i] != 0) 
			num[i - nxt[i]]++;

	ll ans = (ll)SZ(s1) * SZ(s2);
	p = 1;
	for (int i = 0; i < SZ(s2); ++i) {
		p = ch[p][s2[i] - 'a'];
		ans -= (ll)num[i] * v[p];
	}
	cout << ans << '\n';
}

K

Solved: 02:12 BPM136
两个串互为subsequence iff 两个串的t字符集相同 和 s串的到最后的某个不在t串中出现的字符的前缀完全相同
然后map套map就好了

#include 

using namespace std;

#define SZ(x) ((int)(x).size())

map<unsigned, map<string, vector<int> > > g;

int main() {
	int n;
	cin >> n;
	string s, t;
	for (int i = 0; i < n; ++i) {
		cin >> s >> t;
		unsigned st = 0;
		for (auto& c : t) 
			st |= 1u << (c - 'a');
		int pos = 0;
		for (int j = SZ(s) - 1; j >= 0; --j)
			if (((1u << (s[j] - 'a')) & st) == 0) {
				pos = j + 1;
				break;
			}
		auto& mt = g[st];
		mt[s.substr(0, pos)].push_back(i + 1);
	}

	int ans = 0;
	for (auto& p : g) {
		auto& mt = p.second;
		ans += SZ(mt);
	}
	cout << ans << '\n';
	for (auto& p : g) {
		auto& mt = p.second;
		for (auto& v : mt) {
			cout << SZ(v.second);
			for (auto& id : v.second)
				cout << ' ' << id;
			cout << '\n';
		}
	}
}

L

Solved: 00:33 BPM136
二分后判定即可

#include 

using namespace std;

using ll = long long;

ll n, m, a, b, k, x, y;

bool check(ll t) {
	return min(t, a) * x + min(t, b) * y >= t * k;
}

int main() {
	cin >> n >> m >> a >> b >> k;
	x = y = m / 2;
	if (m % 2)
		++x;
	ll l = 1, r = n;
	ll ans = 0;
	while (l <= r) {
		ll mid = (l + r) >> 1; 
		if (check(mid)) {
			ans = mid;
			l = mid + 1;
		} else
			r = mid - 1;
	}
	cout << ans << '\n';
	return 0;
}

M

Solved: 00:15 BPM136
温暖的签到
然而我怎么不会线性呢,一眼二分是什么玩意

#include 

using namespace std;

int a[100005];
int v[100005];

bool check(int mid, int n) {
	for (int i = 1; i <= n - mid + 1; ++i) {
		int l = i, r = i + mid - 1;
		if (v[r - 1] - v[l] == mid - 2 && a[l] != a[l + 1] && a[r] != a[r - 1])
			return 1;
	}
	return 0;
}

int main() {
	int n, m;
	ios::sync_with_stdio(0);
	cin >> n >> m;
	for (int i = 1; i <= n; ++i)
		cin >> a[i];
	a[0] = a[n + 1] = -1;
	for (int i = 1; i <= n; ++i)
		if (a[i] != a[i - 1] && a[i] != a[i + 1])
			v[i] = 1;
	for (int i = 1; i <= n; ++i)
		v[i] += v[i - 1];
	int l = 1, r = n;
	int ans = 1;
	while (l <= r) {
		int mid = (l + r) >> 1;
		if (check(mid, n)) {
			l = mid + 1;
			ans = mid;
		} else
			r = mid - 1;
	}
	cout << ans << '\n';
	return 0;
}

你可能感兴趣的:(ACM补题)