nginx學習
阿新 • • 發佈:2020-10-11
A. Copy-paste
給定一串陣列,可以選定兩個數,將其中一個數加上另外一個數。每個數都不能超過個最大值K,問最多能進行幾次這樣的操作。
排序,其他都加上最小的數即可。
#include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <string> #include <vector> #include <utility> #include<map> #include<queue> #include<sstream> #define lc(i) (2*i+1) using namespace std; typedef long long ll; typedef pair<int, int> P; const ll mod = 998244353 ; ll dataa[1000000 + 5]; int main(){ ll n; cin >> n; while (n--) { ll m, k; ll ans = 0; cin >> m >> k; for (int i = 0; i < m; i++)scanf("%lld", &dataa[i]); sort(dataa, dataa + m); for (int i = 1; i < m; i++)ans += (k - dataa[i]) / dataa[0]; cout << ans << '\n'; } }
B. Two Arrays
給定個值T,和一串數列,將其分為兩部分,使每部分中一對數相加等於T的對數最小
排序,對於每個數x,二分T-x,標記上不同的顏色,x=T/2時,標記一半的x為黑,另一半為白。
#include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <string> #include <vector> #include <utility> #include<map> #include<queue> #include<sstream> #define lc(i) (2*i+1) using namespace std; typedef long long ll; typedef pair<int, int> P; const ll mod = 998244353; P dataa[1000000 + 5]; int col[1000000 + 5] = {}; bool cmp(P a, P b) { return a.first < b.first; } int main() { ll n; cin >> n; while (n--) { ll m, k; ll ans = 0; cin >> m >> k; for (int i = 0; i < m; i++)scanf("%lld", &dataa[i].first), col[i] = -1, dataa[i].second = i; sort(dataa, dataa + m); for (int i = 0; i < m; i++) { if (col[dataa[i].second] == -1) { col[dataa[i].second] = 0; ll l = lower_bound(dataa + i + 1, dataa + m, P(k - dataa[i].first, 0), cmp) - dataa; if (l == m)continue; if (dataa[l].first != dataa[i].first) for (; dataa[l].first == k - dataa[i].first; l++) col[dataa[l].second] = 1; else { int tmp = 0; for (; dataa[l].first == k - dataa[i].first&&l<m; l++) col[dataa[l].second] = tmp ^ 1, tmp ^= 1; } } } for (int i = 0; i < m; i++) printf("%d ", col[i]); printf("\n"); } }
C. k-Amazing Numbers
定義K-number為在陣列中任意長度都為K的區間內都出現的最小數,輸出K等於1到n的K-number
維護每個數字在陣列中出現的位置,從小到大尋找該數字對應的最小K。
可以知道,當一個數滿足K-number,當K更大時這個數也能滿足。
#include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <string> #include <vector> #include <utility> #include<map> #include<queue> #include<sstream> #define lc(i) (2*i+1) using namespace std; typedef long long ll; typedef pair<int, int> P; const ll mod = 998244353 ; int dataa[1000000 + 5]; int datab[1000000 + 5]; int datac[1000000 + 5]; int ans[1000000 + 5] = {}; vector<int> e[300000 + 5]; bool cmp(P a, P b) { return a.first < b.first; } int main(){ ll n; cin >> n; while (n--) { ll m; cin >> m; for (int i = 0; i < m; i++)scanf("%lld", &dataa[i]),ans[i]=-1,datab[i]=dataa[i],e[i]=vector<int>(),e[i].push_back(-1); ans[m] = -1; sort(dataa, dataa + m); //sort(datac, datac + m); ll len = unique(dataa, dataa + m) - dataa; for (int i = 0; i < m; i++)datab[i] =lower_bound(dataa,dataa+len,datab[i])-dataa,e[datab[i]].push_back(i); for (int i = 0; i < len; i++) { ll max1 = e[i][0]; e[i].push_back(m); for (int j = e[i].size() - 1; j > 0; j--)e[i][j] = e[i][j] - e[i][j - 1],max1=max(max1,(ll)(e[i][j])); if (ans[max1] == -1)ans[max1] = dataa[i]; } for (int i = 1; i <=m; i++) { if (i != 1 && (ans[i] == -1||(ans[i]>ans[i-1]&&ans[i-1]!=-1)))ans[i] = ans[i - 1]; printf("%d ", ans[i]); } printf("\n"); } }
D. Make Them Equal
給定一個數列,可以進行以下操作:
選定i,j,x
ai=ai-x*i,aj=aj+x*i
在3n次內令數列全部相同
當我們把所有數都加到a1上,我們就能隨意分配數字
我們可以先把a1的一部分轉移到ai上,令ai%i==0,再把ai全部轉喲到a1.
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <utility>
#include<map>
#include<queue>
#include<sstream>
#define lc(i) (2*i+1)
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const ll mod = 998244353;
int dataa[1000000 + 5];
int ans[1000000 + 5][3] = {};
bool cmp(P a, P b) {
return a.first < b.first;
}
int main() {
ll n;
cin >> n;
while (n--)
{
ll cnt = 0;
ll m;
cin >> m;
dataa[0] = 0;
for (int i = 1; i <= m; i++) {
scanf("%d", &dataa[i]);
dataa[0] += dataa[i];
}
if ((dataa[0] % m)) {
printf("-1\n");
continue;
}
for (int i = 2; i <= m; i++) {
if (dataa[i] % i == 0) {
ans[cnt][0] = i;
ans[cnt][1] = 1;
ans[cnt++][2] = dataa[i] / i;
}
else {
ans[cnt][0] = 1;
ans[cnt][1] = i;
ans[cnt++][2] = i - dataa[i] % i;
ans[cnt][0] = i;
ans[cnt][1] = 1;
ans[cnt++][2] = (dataa[i]+i-1) / i;
}
}
for (int i = 2; i <= m; i++) {
ans[cnt][0] = 1;
ans[cnt][1] = i;
ans[cnt++][2] = dataa[0]/m;
}
printf("%d\n", cnt);
for (int i = 0; i <cnt; i++)printf("%d %d %d\n", ans[i][0], ans[i][1], ans[i][2]);
}
}
E. XOR Inverse
給定陣列,找到個數x,用陣列每個數異或x,新陣列中逆序對最少
先用字典樹維護陣列中的二進位制數,並且每個節點中存著該節點的編號。從高到低位貪心選取逆序對小的(0或1)
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <utility>
#include<map>
#include<queue>
#include<sstream>
#define lc(i) (2*i+1)
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
ll trie[5000000][2];
ll tot = 0;
ll ans[40][2] = {};
vector<int> e[5000000];
void ins(int k, int pos) {
ll p = 0,c;
for (int i = 30; i >= 0; i--) {
c = (k>>i) & 1;
if (trie[p][c] == 0)trie[p][c] = ++tot;
p = trie[p][c];
e[p].push_back(pos);
}
}
void dfs(int k, int pos) {
//if (pos == -1)return;
ll l = trie[k][0], r = trie[k][1];
if (l)dfs(l, pos - 1);
if (r)dfs(r, pos - 1);
if (!trie[k][0] || !trie[k][1])return;
ll tmp = 0, ans1 = 0;
for (int i = 0; i < e[l].size(); i++) {
while (tmp < e[r].size() && e[r][tmp] < e[l][i])tmp++;
ans1 += tmp;
}
ans[pos][0] += ans1;
ans[pos][1] += (ll)e[l].size() * e[r].size() - ans1;
}
int main() {
ll n;
cin >> n;
for (int i = 1; i <= n; i++) {
int tmp;
scanf("%d", &tmp);
ins(tmp, i);
}
dfs(0, 30);
ll res=0, x=0;
for (int i =0; i <= 30; i++) {
if (ans[i][0] <= ans[i][1])
res += ans[i][0];
else {
res += ans[i][1];
x += (1 << i);
}
}
cout << res << ' ' << x;
}