25暑假hdu
HDU 1 1010中位数
题意:求所有子区间内两端点和区间中位数的乘积。
题解(参考官方):
考虑枚举每个点作为中位数所对应的区间,则中位数的一个显然特征是"大于等于其的数=小于等于其的数",这两者可以通过一个简单的数组来表示:如大于\(a[i]\)为1,小于\(a[i]\)为-1,对于新的数组求前缀和,假设为\(sum\)数组,若\(sum[l-1] = sum[r]\),即在\([l, r]\)内\(sum\)数组和为0,就能反得出上面的特征,从而求出\(a[i]\)为中位数所对应的区间,遍历即可。
这题在赛时队友提出了一个很难hack的\(dp\)思路,爽吃三发罚时之后才找到反例hack。
在写代码的时候出现了瓶颈,想了很久都是\(O(n^3)\)的做法,无法达到题解所说的\(O(V*n^2)\),后来翻阅标程,并通过AI进行解释理解后,下面是我对源代码给出的较为通俗的解释,希望能帮到大家:
首先贴关键代码
for (j = 1; j <= n; j++)
sum[j] = sum[j - 1] + b[j];
for (j = 0; j < i; j++)
s[sum[j] + P] += j + 1;
for (; j <= n; j++)
ans += j * s[sum[j] + P] * a[i];
这三个循环,我们来逐一解答:
首先第一个循环是理解起来较为简单的,就是对前者\(cnt\)数组的前缀和(如果到这里还看不懂的小伙伴要重新理解题目和上面的题解)。
第二个循环,个人认为这是在对应的\(sum\)值上存储左端点值,那如果\(sum[j]\)是负值呢?所以我们需要一个很大的偏移量\(P\),来让无论\(sum[j]\)多小的情况下,经过与偏移量相加之后都是正数。在这道题的标程中,\(P=2001\)。
第三个循环,可以看到在循环条件上和第二个循环正好互补,由此判断这里进行到了匹配右端点,计算最终结果的阶段。那为什么\(s[sum[j]+P]\)明明在上一个循环中可能由不同的值相加而成的,这里却可以直接相乘呢?我们可以思考一下最开始题解所给的性质:
若\(sum[l-1] = sum[r]\),即在\([l, r]\)内\(sum\)数组和为0。
如果此时\(sum[j]+P\)相等的话,那么就一定会有原本的 \(sum[j]\)相等,正好符合了题目要求的性质!那么此时就是一个左端点对应了多个右端点。再加上题目所求的是\(i*j*a[i]\),实际上这里的右端点并不需要区分,在最后求结果的时候都能通过乘法结合律加到一起算。
还有最鸡贼的一点:s数组要开\(long long\)不然会炸!
HDU 1 1009子序列
题意:在\(n\)的排列中找出两端大于中间的最长子序列(保持顺序一致但并不要求连续)
题解:
在赛时想到的是通过\(idx\)和原数组的关系,但是我没有由此想到在\(O(n)\)时限内的解法,反复猜测后想到了题给正解但是码力一坨以及自己的不确定导致彻底烂尾。
官方题解的解法在于"从大到小往下顺",先从最大的两个点开始,然后依次加入较小的数,判断是否存在题目中的更优解。
题解中所给的每次更新的\((r-l+1)-(n-i-1)\)意为:在原有的区间长度的基础上,减去大于新的边界的数。
https://acm.hdu.edu.cn/contest/view-code?cid=1172&rid=18255
HDU1 1006 景区建设
题意:一个图内,游客从\((1, 1)\)点要走到所有区域,游客只会从高到低走,建设传送门和之间的传送通道都需要花费一定的代价,求走到所有区域的最小总代价。
题解:
首先\(dfs\)出所有不需要传送门就能到达的区域,然后对剩下没有遍历到的点从高到低取,每取一次点\(dfs\)一次,将所有传送门装一个\(set\)里面,通过\(set\)的排序后,所需的代价就是两两元素相邻的代价。
有点暴力的意思,很可惜。
#include <algorithm>
#include <bits/stdc++.h>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <set>
#include <utility>
#include <vector>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define endl '\n'
#define cty cout<<"Yes"<<endl
#define ctn cout<<"No"<<endl
#define dbg(x) cout<<#x<<" : "<<x<<endl
#define int long long
const int mxn = 4e5+10;
inline int read(){
int N = 0;char ch = getchar();
while (ch>'9'||ch<'0') ch = getchar();
while (ch>='0'&&ch<='9') N = N*10+ch-'0',ch = getchar();
return N;
}
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int mod = 998244353;
ll fastpow(ll a,ll n){
if(a==0) return 0;
if(n < 0){
a = 1/a;
n = -n;
}
ll res = 1;
a%=mod;
while(n){
if(n & 1) res = (res*a)%mod;
a = (a*a)%mod;
n>>=1;
}
return res;
}
const ll asd = (1ll<<34);
int n,m;
int a[110][110];
bool vis[110][110];
int px[4] = {0,1,0,-1};
int py[4] = {1,0,-1,0};
// int calc(pair<int, pair<int, int>> a,pair<int, pair<int, int>> b){
// return asd+919810ll*abs(a.first-b.first)+114ll*abs(a.second.first-b.second.first)+5141ll*abs(a.second.second-b.second.second);
// }
ll calc(int x0, int y0, int a0, int x1, int y1, int a1) {
return (1ll << 34) + 114ll * abs(x0 - x1) + 5141ll * abs(y0 - y1) + 919810ll * abs(a0 - a1);
}
ll calc(pair<int, pair<int, int>> p1, pair<int, pair<int, int>> p2) {
return calc(p1.second.first, p1.second.second, p1.first, p2.second.first, p2.second.second, p2.first);
}
int cnt = 0;
void bfs(int x,int y){
queue<pair<int, int>> q;
q.push({x,y});
vis[x][y] = true;
while(!q.empty()){
auto t = q.front();
q.pop();
int tx = t.first,ty = t.second;
cnt++;
for(int i = 0;i < 4; i++){
int xx = tx+px[i],yy = ty+py[i];
if(xx<1||xx>n||yy<1||yy>m||vis[xx][yy]) continue;
if(a[xx][yy]<=a[tx][ty]&&!vis[xx][yy]){
q.push({xx,yy});
vis[xx][yy] = true;
}
}
}
}
void LonelyLunar_solve(){
memset(vis, false, sizeof(vis));
cnt = 0;
vector<pair<int, pair<int, int>>> h;
cin>>n>>m;
for(int i = 1;i <= n; i++){
for(int j = 1;j <= m; j++){
cin>>a[i][j];
h.push_back({a[i][j],{i,j}});
}
}
sort(h.begin(),h.end());
bfs(1,1);
ll ans = 0;
if(cnt==n*m){
cout<<"0"<<endl;
return ;
}
set<pair<int, pair<int, int>>> st;
pair<int, pair<int, int>> p0 = {a[1][1],{1,1}};
st.insert(p0);
while(cnt<n*m){
auto p = h.back();
h.pop_back();
int x = p.second.first,y = p.second.second;
if(vis[x][y]==true) continue;
st.insert(p);
auto it = st.find(p);
auto it2 = it;
it2++;
if(it==st.begin()){
ans+=calc(*it,*it2);
}
else if(it2==st.end()){
auto it3 = it;
it3--;
ans+=calc(*it3,*it);
}
else{
auto it3 = it;
it3--;
ans+=calc(*it3,*it);
ans+=calc(*it,*it2);
ans-=calc(*it3,*it2);
}
bfs(x, y);
}
cout<<ans<<endl;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int _ = 1;
cin>>_;
while(_--){
LonelyLunar_solve();
}
return 0;
}