其他分享
首页 > 其他分享> > Codeforces Round #816 (Div. 2)

Codeforces Round #816 (Div. 2)

作者:互联网

\(\quad\) 今早头一次睡到了九点,大概昨天在健身房确实训练过度了,胸廓酸软,大腿一直颤抖。
\(\qquad\) 下午去了趟实验室,完成了我的第一个物联网程序虽然很水。慢慢试着用\(VS\quad CODE\)切题,效率一般,命令行与编译指令反而不知不觉间搞懂了……还是很垃圾,一整天只做出五道题,其中两道还是面向题解编程,日语没学,高数没学,前端没学,堆积的论文一篇没看,嗯,真是完美的一天。看着一整页的\(WA\)和自己初中生都不如的\(rating\),也只好苦笑一声继续推式子,一抬头发现那个女孩又给我发了消息,这次问的是道很简单的计数题,我正打算告诉她没设初始量时,想了想,决定晚点回。最近与她走得太近了点,有些行为事实上与情侣无异了,对我来说,过分了。现在的我还没有对任何人负起责任的资本,既然不想耽误别人的青春,还是保持距离的好。
\(\qquad\)明天就正式开课了,又会有幻梦的破碎,恍惚间已经预见到了。我还是想把一天一套\(Div.2\)的训练量坚持下去,现在的效率是不行的。得真正掌握些许许本领,才能堂堂正正地回到那座山。
\(\qquad\)说起来,九月的话,那个人的生日也近了

简单找规律

$code$
# include "bits/stdc++.h"
using namespace std;
int main() {
# ifdef QWQ
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
# endif
    // ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int test;
    cin >> test; 
    while(test--) {
        int n, m;
        cin >> n >> m;
        if(n == 1 && m == 1) {
            cout << "0\n";
        }
        else {
            cout << (n + m - 2) * 2 - max(m - 2, n - 2) << "\n";
        }
    }
    return 0;
}
/*
(m + n - 2) * 2 - max(m - 2, n - 2)
*/

贪心,分析,普适化解构

$code$
# include "bits/stdc++.h"
using namespace std;
# define int long long
# undef int
int main() {
# define int long long
# ifdef QWQ
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
# endif
//    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int tt;
    cin >> tt;
    for(int t = 1; t <= tt; ++t) {
        int n, k, b, s;
        cin >> n >> k >> b >> s;
        if(k * b + (k - 1) * n < s || s < b * k) {
            cout << "-1\n";
        }
        else {
            bool flag = true;
            vector<int> ans;
//            if(!ans.empty()) cout << "*****";
            s -= b * k;
            ans.push_back(b * k);
            while(s > 0) {
                int x = min(s, k -  1);
//                 cout << x << " ** " << endl;
                s -= x;
                ans.push_back(x);
                if(ans.size() > n + 1) {
                    flag = false;
                    break;
                }
            }
            if(flag == false) {
                cout << "-1\n";
            }
            else {
            	if(ans.size() >= 2) {
            		ans[1] += ans[0];
            		ans.erase(ans.begin());
				}
                for(auto x : ans) {
                    cout << x << " ";
                }
                for(int i = ans.size() + 1; i <= n; ++i) {
                    cout << "0 ";
                }
                putchar('\n');
            }
        }
	}
    return 0;
}
/*
6
3 6 3 19
5 4 7 38
5 4 7 80
99978 1000000000 100000000 1000000000000000000
1 1 0 0
4 1000000000 1000000000 1000000000000000000
*/
/*
1
3 6 3 19
*/
/*
10
1 6 3 100
3 6 3 12
3 6 3 19
5 4 7 38
5 4 7 80
99978 1000000000 100000000 1000000000000000000
1 1 0 0
4 1000000000 1000000000 1000000000000000000
5 3 0 9
5 3 1 12

//n k b s
//
//5 3 0 9
// 0 2
// 9 
*/

全局思考每个点变化前后贡献变化,发现并基于边界展开讨论。过程中有些范围处理与线段树类似,弄清对象不足一提。

$code$
# include "bits/stdc++.h"
using namespace std;
int main() {
# ifdef QWQ
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
# endif
    int n, m;
    cin >> n >> m;
    vector<int> a(n + 2, 0);
    for(int i = 1; i <= n; ++i) {
        cin >> a[i];
    }
    long long ans = 1ll * n * (n + 1) >> 1;
    for(int i = 1; i <= n; ++i) {
        if(a[i] != a[i + 1]) {
            ans += 1ll * (n - i) * i;
        }
    }
    // cout << ans << endl;
    while(m--) {
        int x;
        cin >> x;
        if(a[x] != a[x - 1]) ans -= 1ll * (n - x + 1) * (x - 1);
        if(a[x] != a[x + 1]) ans -= 1ll * (n - x) * x;
        cin >> a[x];
        if(a[x] != a[x - 1]) ans += 1ll * (n - x + 1) * (x - 1);
        if(a[x] != a[x + 1]) ans += 1ll * (n - x) * x;
        cout << ans << "\n";
    }
    return 0;
}

二进制问题,联想到基于数位贪心

$code$
# include "bits/stdc++.h"
using namespace std;
bool bit(int x, int i) {
	return x & (1 << i - 1);
}
int main() {
# ifdef QWQ
freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
# endif
	int n, m;
	cin >> n >> m;
	vector<int> ans(n + 1);
	vector G(n + 1, vector<pair<int, int>>());
	vector f(n + 1, bitset<32>());
	for(int i = 1; i <= m; ++i) {
		int u, v, w;
		cin >> u >> v >> w;
		for(int j = 1; j <= 30; ++j) {
			if(bit(w, j) == false) {
				f[u][j] = f[v][j] = true; // here, we can't set f(node)(digit) := true when bit(w, j) == true, since some v may hasn't appered even once
			}
		}
		if(u == v) {
			ans[u] = w;
			continue;	
		}
		G[u].push_back({v, w});
		G[v].push_back({u, w});
	}
	
	auto check = [&](int u, int i) -> bool {
		for(auto [v, w] : G[u]) {
			if(bit(w, i) == false) continue;
			if(u < v) {
				if(f[v][i] == true) return true;
			}
			else if(bit(ans[v], i) == false) return true; 
		}
		return false;
	};
	
	for(int i = 1; i <= 30; ++i) {
		for(int j = 1; j <= n; ++j) {
			if(check(j, i) == true) {
				ans[j] |= (1 << i - 1);
			}
		}
	}
	
	for(int i = 1; i <= n; ++i) cout << ans[i] << " ";
	return 0;
}

易知\(k=1\)时的情况,一定先走最短路最后才乌鸦坐飞机最优,算下\(\min {\{dis[u] + (v - u)^{2}} \}\)就可以。倘若每多一次飞翔,就相当于在上一次的最短(优?)路中再\(DP\)一次。跑\(K\)遍堆优\(dij\)即可。
注意到该题中,转移方程\(\{ dis_{new}= min \{dis_{now}+(u-v)^{2}\} \}\),可以化作 \(dis_{now}u + u^{2} = 2 * v * u + dis_{new}v - v ^{2}\),于是斜率优化,凸包维护。
需要注意的一点是,该题图像不保证连通,因此\(dij\)过程中需要把每个点都投入堆中。

$code$
# include "bits/stdc++.h"
using namespace std;
const int N = 100003;
int main() {
# define int long long
# ifdef QWQ
freopen("in.txt", "r", stdin);
# endif
	int n, m, K;
	cin >> n >> m >> K;
	vector G(n + 1, vector<pair<int, int>>());
	
	for(int i = 1; i <= m; ++i) {
		int u, v, w;
		cin >> u >> v >> w;
		G[u].push_back({v, w});
		G[v].push_back({u, w});
	}
	
	vector<int> dis(n + 1);
	
	auto dijkstra = [&]() -> void {
		struct node {
			int v, w;
			bool operator < (const node &x) const {
				return w > x.w;
			}
		};
		priority_queue<node> q;
		for(int i = 1; i <= n; ++i) q.push({i, dis[i]});
		while(!q.empty()) {
			auto [u, ww] = q.top();
			q.pop();
			if(ww != dis[u]) continue;
			for(auto [v, w] : G[u]) {
				if(dis[v] > dis[u] + w) {
					dis[v] = dis[u] + w;
					q.push({v, dis[v]});
				}
			}
		}
	};
	
	for(int i = 1; i <= n; ++i) dis[i] = 1ll << 60;
	dis[1] = 0;
	dijkstra();
	
	vector<int> stk(n + 2); // here, must >= n + 2, if we don't wanna get a whole page of unknown RE
	vector<int> dis_new(n + 1);
	
	auto slope = [&](int x, int y) -> double {
		return 1.0 * (dis[y] + y * y - dis[x] - x * x) / (y - x);
	};
	
	while(K--) {
		int top = 1;
		stk[top] = 0;
		for(int i = 1; i <= n; ++i) {
			while(top > 1 && slope(stk[top - 1], stk[top]) > slope(stk[top], i)) --top;
			stk[++top] = i;
		}
		int now = 1;
		for(int i = 1; i <= n; ++i) {
			while(now < top && slope(stk[now], stk[now + 1]) < 2 * i) ++now;
			dis_new[i] = dis[stk[now]] + (i - stk[now]) * (i - stk[now]);
		}
		for(int i = 1; i <= n; ++i) dis[i] = dis_new[i];
//		memcpy(dis, dis_new, (n + 1) * sizeof(int));
		dijkstra();
	}
	
	for(int i = 1; i <= n; ++i) cout << dis[i] << " ";
	return 0;
}
/*
2 1 1
2 1 893746473
*/

标签:std,cout,int,Codeforces,vector,ans,Div,816,dis
来源: https://www.cnblogs.com/bingoyes/p/16656664.html