題目鏈接:https://codeforces.com/contest/1248
水題
#include<bits/stdc++.h>
using namespace std;
const int mx = 1e5+5;
typedef long long ll;
int a[mx],b[mx];
int main(){
int t;
scanf("%d",&t);
while(t--){
int n,m;
scanf("%d",&n);
ll c[2] = {0,0};
ll d[2] = {0,0};
for (int i=1;i<=n;i++) {
scanf("%d",a+i);
c[a[i]%2]++;
}
scanf("%d",&m);
for (int i=1;i<=m;i++) {
scanf("%d",b+i);
d[b[i]%2]++;
}
printf("%lld\n",c[0]*d[0]+c[1]*d[1]);
}
return 0;
}
意思就是一半的和做一邊,另一半的和做另一邊,平方的話讓一邊越大越好就行了
#include<bits/stdc++.h>
using namespace std;
const int mx = 1e5+5;
typedef long long ll;
int a[mx],b[mx];
int main(){
int n;
scanf("%d",&n);
int sum = 0;
for(int i=1;i<=n;i++){
scanf("%d",a+i);
sum += a[i];
}
sort(a+1,a+1+n);
int beg = n / 2,ret = 0;
for (int i=1;i<=beg;i++)
ret += a[i];
printf("%lld\n",1ll*ret*ret+1ll*(sum-ret)*(sum-ret));
return 0;
}
C - Ivan the Fool and the Probability Theory
不難證明除了黑白交替的方塊意外,其他的方塊數都是取決於第一行的擺放方案,後面跟隨第一行都擺放都是固定的。然後一行的dp方案只要記最後是連續兩個一樣的還是不一樣的方案數就可以,另外行數對黑白交替的方案數的影響其實是一樣的。
#include<bits/stdc++.h>
using namespace std;
const int mx = 1e5+5;
const int mod = 1e9 + 7;
typedef long long ll;
ll dp[mx][2];
int main(){
int n,m;
scanf("%d%d",&n,&m);
if (m > n) swap(n,m);
dp[1][0] = 1;
for (int i=2;i<=n;i++) {
dp[i][0] = (dp[i-1][0]+dp[i-1][1])%mod;
dp[i][1] = dp[i-1][0];
}
ll ans = (dp[n][0] + dp[n][1] - 1)*2 + (dp[m][0] + dp[m][1])*2;
ans %= mod;
printf("%lld\n",ans);
return 0;
}
D2 - The World Is Just a Programming Task (Hard Version)
利用棧的原理如果括號最後不完全匹配,那麼肯定是會是這樣情況))))((((,那麼要想有解必須左括號數量等於右括號數量。
不難發現我們能操作的空間只有...)..)...(...(...也就是最多兩個不匹配的括號
1、將原來匹配的括號互換(()) ==> )()(
2、將兩個不匹配的變成0個,))(( ==> ()()
3、減少一個不匹配,)( ==>()
4、變換一個不匹配的位置 ())(== > )()(
#include<bits/stdc++.h>
using namespace std;
const int mx = 3e5+5;
const int mod = 1e9 + 7;
typedef long long ll;
int n;
int sum[mx];
char s[mx];
int lp[mx],rp[mx],psiz;
int cnt[mx],lc[mx],rc[mx];
bool vis[mx],mark[mx];
int fa[mx];
bool get_pos() {
stack <int> s1;
int j = 0;
for (int i=1;i<=n;i++) {
if (s[i] == '(') {
s1.push(i);
} else {
if (s1.empty()) {
lp[psiz++] = i;
mark[i] = 1;
continue;
}
int now = s1.top();
lc[now] = i, rc[i] = now;
s1.pop();
}
}
if (s1.size() != psiz) return 0;
reverse(lp,lp+psiz);
while (!s1.empty()) {
rp[j++] = s1.top();
mark[rp[j-1]] = 1;
s1.pop();
}
reverse(rp,rp+psiz);
return 1;
}
inline int get_int(int l,int r) {
return sum[r] - sum[l];
}
void get_val() {
stack <int> s1;
for (int i=1;i<=n;i++) {
if (mark[i]) continue;
if (s[i]=='(') {
s1.push(i);
} else {
int now = s1.top();
s1.pop();
if (!s1.empty()) {
cnt[s1.top()]++;
fa[now] = s1.top();
}
else {
sum[now]++;
vis[now] = 1;
}
}
}
}
int main(){
scanf("%d",&n);
scanf("%s",s+1);
int ans,l,r;
if(!get_pos()) return 0*puts("0\n1 1");
get_val();
for (int i=1;i<=n;i++) sum[i] += sum[i-1];
rp[psiz] = n + 1;
lp[psiz] = 0;
sum[n+1] = sum[n];
ans = get_int(lp[0],rp[0]) + (psiz > 0);
l = 1,r = 1;
for (int i=lp[0]+1;i<rp[0];i++) {
if (s[i]=='(') {
if (vis[i]){
if (cnt[i] + 1 > ans) {
ans = cnt[i] + 1;
l = i, r = lc[i];
}
} else if (vis[fa[i]]){
int ret = get_int(lp[0],rp[0]) + cnt[i] + 1 + (psiz > 0);
if (ret > ans) {
ans = ret;
l = i, r = lc[i];
}
}
}
}
if (psiz) {
int ret = get_int(lp[1],rp[1]) - get_int(lp[0],rp[0]) + (psiz>1) + 1;
if (ret > ans) {
ans = ret;
l = lp[0], r = rp[0];
}
if (psiz > 1) {
ret = get_int(lp[2],rp[2]) + 2;
ret -= get_int(lp[1],lp[0]) + get_int(rp[0],rp[1]);
ret += (psiz > 2);
if (ret > ans) {
ans = ret;
l = lp[1],r = rp[1];
}
}
int L = lp[0];
while (L != lp[1]) {
if (vis[L]) {
ret = get_int(lp[0],rp[0]) + 2;
ret += cnt[L];
if (ret > ans) {
ans = ret;
l = L, r = lc[L];
}
}
L--;
}
int R = rp[0];
while (R != rp[1]) {
if (vis[R]) {
ret = get_int(lp[0],rp[0]) + 2;
ret += cnt[R];
if (ret > ans) {
ans = ret;
l = R, r = lc[R];
}
}
R++;
}
}
printf("%d\n%d %d\n",ans,l,r);
return 0;
}
用三個隊列維護:
1、優先隊列維護可以去泡麪的時間
2、在機子前排隊的隊列
3、可以取泡麪但是由於前面的人不在而還沒去的優先隊列
#include<bits/stdc++.h>
#define x first
#define y second
using namespace std;
const int mx = 1e5+5;
const int mod = 1e9 + 7;
typedef long long ll;
typedef pair <int,int> pa;
int n,m;
pa s[mx];
ll ret[mx];
int sum[mx];
priority_queue <int,vector<int>,greater<int>> sq;
queue <int> nq;
void add(int x,int v) {
for (;x<=n;x+=x&(-x))
sum[x] += v;
}
int get_sum(int x) {
int ans = 0;
while (x) {
ans += sum[x];
x -= x&(-x);
}
return ans;
}
void to_queue (int& j,ll times) {
while (j <= n && s[j].x <= times) {
if (get_sum(s[j].y) == s[j].y) {
nq.push(s[j].y);
add(s[j].y,-1);
} else {
sq.push(s[j].y);
}
j++;
}
}
int main(){
scanf("%d%d",&n,&m);
int u;
for (int i=1;i<=n;i++) {
scanf("%d",&u);
s[i] = pa(u,i);
add(i,1);
}
ll times = 0;
sort(s+1,s+1+n);
for (int i=1,j=1;i<=n;i++) {
if (nq.size() == 0 && s[j].x > times)
times = s[j].x;
to_queue(j, times);
int id = nq.front(); nq.pop();
times += m, ret[id] = times;
to_queue(j, times);
add(id,1);
if (!sq.empty() && get_sum(sq.top()) == sq.top()) {
int now = sq.top();
nq.push(now); add(now,-1);
sq.pop();
}
}
for (int i=1;i<=n;i++)
printf("%lld ",ret[i]);
return 0;
}
一個結論就是人和貓的編號一定是互補的,這個由第i個人肯定和第i只貓有連邊推出
然後就是建邊找出度爲0的強連通分量
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int mx = 2e6 + 10;
int n,m;
bool vis[mx];
int sta[mx],siz,is;
int dfn[mx],id[mx];
int be[mx],ty;
vector <int> g[mx];
void tarjan(int u) {
dfn[u] = id[u] = ++is;
sta[++siz] = u;
vis[u] = 1;
for (int v:g[u]) {
if (!dfn[v]) {
tarjan(v);
id[u] = min(id[u],id[v]);
} else if (vis[v])
id[u] = min(id[u],dfn[v]);
}
if (id[u]==dfn[u]) {
ty++;
while (sta[siz] != u) {
be[sta[siz]] = ty;
vis[sta[siz]] = 0;
siz--;
}
be[u] = ty,vis[u] = 0,siz--;
}
}
int cnt_one() {
int cnt = 0;
for (int i=1;i<=n;i++)
if (be[i]==1) cnt++;
return cnt;
}
int main() {
int t;
scanf("%d",&t);
while (t--) {
scanf("%d%d",&n,&m);
for (int i=1;i<=2*n;i++)
g[i].clear();
ty = is = siz = 0;
for (int i=1;i<=2*n;i++)
dfn[i] = vis[i] = 0;
for (int i=0,u,v;i<m;i++) {
scanf("%d%d",&u,&v);
if (u==v) g[v+n].push_back(u);
else g[u].push_back(v+n);
}
if (n == 1) {
puts("No");
continue;
}
for (int i=1;i<=n;i++) if(!dfn[i])
tarjan(i);
int cnt = cnt_one();
if (cnt == n) puts("No");
else {
//cout << cnt << endl;
puts("Yes");
printf("%d %d\n",cnt,n-cnt);
for (int i=1;i<=n;i++) if (be[i]==1)
printf("%d ",i);
puts("");
for (int i=1;i<=n;i++) if (be[i]!=1)
printf("%d ",i);
puts("");
}
}
return 0;
}