公告:
鹿邑广利置业有限公司官方网站,诚信为本:市场永远在变,诚信永远不变。
新闻中心
全国服务电话:联系我们  
400-8888-888
地址:
鹿邑省盐城市射阳海滨国际高尔夫球场对面
座机:
0515-82734567
手机:
15777777777 于总
传真:
0515-66666666
邮箱:
[email protected]
400:
400-8888-888
企业新闻  
当前位置:
2024.05 别急记录发布时间:2024/5/19 1:42:36

1. POI2015 - Podział naszyjnika

考虑对每个位置附一个随机权值,保证序列中所有等于某个数的位置权值异或和为 \(0\)。则一种划分合法当且仅当两个区间异或和都为 \(0\),相当于找到一个区间 \([L,R]\) 异或和为 \(0\)。于是用 umap 记录前缀异或和即可。第二问把每个相同的前缀异或和放到一个 vector 里双指针即可。注意 \([1,i],[i+1,n]\) 之类的划分可能会被统计两次,解决方法是不统计所有以 \(n\) 结尾的区间。

点击查看代码
//P3587
#include <bits/stdc++.h>
using namespace std; typedef long long ll;
void solve();int main(){ solve(); return 0; }const int N = 1e6 + 10;
int n, k, a[N], cnt, mx;
ll xom[N], val[N], ans;
unordered_map<ll, int> mp;
vector<int> g[N];int cl(int x, int y){return min(y - x, x + n - y);
}mt19937 rng(time(0));
uniform_int_distribution<long long>gen(1,0x3f3f3f3f3f3f3f3f);void solve(){srand(unsigned(time(NULL)));mp[0] = ++ cnt;g[mp[0]].push_back(0);scanf("%d%d", &n, &k);for(int i = 1; i <= n; ++ i){scanf("%d", &a[i]);val[i] = gen(rng);xom[a[i]] ^= val[i];}for(int i = 1; i <= n; ++ i){val[i] ^= xom[a[i]];xom[a[i]] = 0;val[i] ^= val[i-1];if(!mp[val[i]]){mp[val[i]] = ++ cnt;}g[mp[val[i]]].push_back(i);}for(int i = 1; i <= cnt; ++ i){int x = g[i].size();if(mp[val[n]] == i){-- x;}ans += (ll)x * (x-1) / 2;int pr = 0;for(int j = 1; j < x; ++ j){while(pr < j && cl(g[i][pr], g[i][j]) < cl(g[i][pr+1], g[i][j])){++ pr;}mx = max(mx, cl(g[i][pr], g[i][j]));}}printf("%lld %d", ans, n - mx - mx);
}

相关资讯[返回列表]

400-8888-888