目录
一、题目报告
T1 贪心 拿了 70分
T2 贪心 拿了 50分
T3 骗分 骗了 10分
T4 骗分 骗了 15分
二、赛中概况
比赛时,先看了看第一题(虚假的一般图最小匹配),嗯,简单的想到了一个贪心的做法,花了大约半个小时打出来了,但是感觉有问题(是真的有问题),就尝试去用区间dp解决,但是推了很久都没有推对,果断放弃。
再看看第二题(序列删除与填充),嗯,没有暴力思路,所以就尝试去打正解一个可行的思路,推了大约30min,又打了接近20min的代码,做出来了,感觉应该大概可能或许有概率AC(然而是我想多了)。
第三题(虚假的斯坦纳树),斯坦纳树?没听过,看了看题目描述,看不太懂,放弃。
第四题(虚假的树直径)今天的虚假东西可真多啊,哎,我貌似会树的直径唉,看了看题,我又想多了。
由于实在不会三四题,甚至连暴力思路都没有,就只好输出了一些“1”,竟然骗了25分!?(数据有点水吧)
三、题目概况
T1.虚假的一般图最小匹配(match)
题目大意
一个个点的完全图,取出
和
个点,求最小的边权
总和。
题目解析
这是一个完全图,说明任意两点之间都有边相连。要求最小值,那么肯定是相邻值的两个点之间的扁选择出来最优,就可以给所有点先按照值排序,求出每每相邻的两个点之间的边权,去利用dp求出最小值即可。
正解代码
#include <cstdio>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <list>
using namespace std;
#define bug printf("--------\n");
#define debug(x) cout << #x << '=' << x << endl;
#define file(FILENAME) freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout);
#define rep(i, a, b) for(int (i) = (a); (i) <= (b); ++(i))
#define inv(x) qpow((x), mod - 2)
#define pb push_back
#define mk make_pair
#define mem(t, v) memset((t), (v), sizeof (t));
#define DBG cerr << __LINE__ << ' ' << __FUNCTION__ << endl;
#define CLOSE ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define N 5005
#define M 10005
#define inf 0x3f3f3f3f3f3f3f3f
#define mod 10007
typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { while (a ^= b ^= a ^= b %= a); return b; }
ll ppow(ll x, ll y) { ll sum = 1; while (y) { if (y & 1) sum *= x; y >>= 1, x *= x; } return sum; }
bool prime(ll x) { for (int i = 2; i * i <= x; i++) { if (x % i == 0) return false; } return true; }
// ll n, m, l, k, p, i;
// ll a[N], b[N];
// bool vis[N];
// stack<ll> st;
// queue<ll> q;
// map<ll,ll> mp;
// vector<ll> v;
// char c;
// string s;
// ll ans, cnt, sum, num;
// struct node {
// ll x;
// ll y;
// }d[N];
ll n,m;
ll a[N];
ll dp[N][N];
int main() {
// file("match")
// CLOSE
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>a[i];
dp[0][i]=dp[1][i]=inf;
}
sort(a+1,a+n+1);
for(int i=2;i<=n;i++){
for(int j=1;j<=m;j++){
dp[i][j]=dp[i-1][j];
dp[i][j]=min(dp[i-2][j-1]+a[i]-a[i-1],dp[i][j]);
}
}
cout<<dp[n][m];
return 0;
}
T2.序列删除与填充(delfill)
题目大意
给定一个长度为的序列,从中删除并插入一些数,求出字典序最小的序列
题目解析
贪心,去通过条件逐一分解成小问题去解决。
推理过程暂无...
正解代码
不知是怎样的玄学问题,它没问题却过不了,当个乐子看吧。
#include <cstdio>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <list>
using namespace std;
#define bug printf("--------\n");
#define debug(x) cout << #x << '=' << x << endl;
#define file(FILENAME) freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout);
#define rep(i, a, b) for(int (i) = (a); (i) <= (b); ++(i))
#define inv(x) qpow((x), mod - 2)
#define pb push_back
#define mk make_pair
#define mem(t, v) memset((t), (v), sizeof (t));
#define DBG cerr << __LINE__ << ' ' << __FUNCTION__ << endl;
#define CLOSE ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define N 200005
#define M 10005
#define inf 0x3f3f3f3f
#define mod 10007
typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { while (a ^= b ^= a ^= b %= a); return b; }
ll ppow(ll x, ll y) { ll sum = 1; while (y) { if (y & 1) sum *= x; y >>= 1, x *= x; } return sum; }
bool prime(ll x) { for (int i = 2; i * i <= x; i++) { if (x % i == 0) return false; } return true; }
ll a[N],aa[N],b[N],k;
bool vis[N];
int main() {
// file("delfill")
// CLOSE
ll t;
cin>>t;
vis[0]=b[0]=0;
while(t--){
ll n;
cin>>n;
ll del=-1;
int flag=-1;
memset(a,0,sizeof a);
memset(b,0,sizeof b);
memset(vis,0,sizeof vis);
k=0;
a[0]=inf;
for(int i=1;i<=n;i++){
cin>>a[i];
aa[i]=a[i];
vis[a[i]]=1;
if(a[i]==0&&flag==-1)flag=i;
}
if(flag==-1){
del=n;
for(int i=2;i<=n;i++){
if(a[i]<a[i-1]){
del=i-1;
break;
}
}
}
else{
bool flag_bool=0;
for(int i=2;i<=flag-1;i++){
if(a[i]<a[i-1]){
del=i-1;
vis[a[del]]=0;
flag_bool=1;
break;
}
}
bool nomin=0;
if(!flag_bool){
ll maxx_need=0;
for(int i=1;i<=n;i++){
if(!vis[i]){
maxx_need=i;
break;
}
}
if(flag>1&&a[flag-1]>maxx_need){
del=flag-1;
vis[a[del]]=0;
}
else{
ll minn_need=inf;
for(int i=1;i<=n;i++){
if(!vis[i]){
minn_need=i;
break;
}
}
ll minn_back=0;
for(int i=flag+1;i<=n;i++){
if(a[i]!=0&&a[i]<a[minn_back])minn_back=i;
}
if(minn_need>a[minn_back]){
del=minn_back;
vis[a[del]]=0;
}
else{
nomin=1;
for(int i=1;i<=n;i++){
if(!vis[i])b[++k]=i;
}
for(int i=flag,j=1;i<=n;i++){
if(aa[i]==0){
aa[i]=b[j++];
}
}
for(int i=2;i<=n;i++){
if(aa[i]<aa[i-1]){
del=i-1;
vis[aa[del]]=0;
break;
}
}
memset(b,0,sizeof b);
k=0;
}
}
}
for(int i=1;i<=n;i++){
if(!vis[i])b[++k]=i;
}
for(int i=flag,j=1;i<=n;i++){
if(a[i]==0&&i!=del){
a[i]=b[j++];
}
}
if(nomin){
for(int i=2;i<=n;i++){
if(a[i]<a[i-1]){
del=i-1;
vis[a[del]]=0;
break;
}
}
}
}
if(del==-1)del=n;
for(int i=1;i<=n;i++){
if(i!=del)cout<<a[i]<<' ';
}
cout<<'\n';
}
return 0;
}
T3.T4.
到现在没有整明白,就忽略掉它们吧。
四、总结
再接再励,争取省一。
本章完...