有一張 \(n\) 個點 \(m\) 條邊的圖,點有點權,邊有邊權。
先手後手輪流染黑白兩色,最後的得分是自己染的點權和 + 兩端均為自己的顏色的邊權和。
雙方都希望自己的得分 - 對手的得分最大,求結果。
\(1 \le n \le 10000, 0 \le m \le 100000\)
這題巨妙無比,真是妙蛙種子吃著妙脆角,秒進了公尺奇妙妙屋,秒到家了。
你可以考慮把每一條邊都分到他所連的 \(2\) 個點上,各一半。
然後對於每條邊,我們有 \(2\) 種可能,如下:
#include #include #include using namespace std;
const int maxn = 10010;
int n, m, u, v, w;
double a[maxn];
double cmp(double x, double y)
int main()
for(int i = 1; i <= m; ++ i)
sort(a + 1, a + n + 1, cmp);
double ans = 0;
for(int i = 1; i <= n; ++ i)
else
}printf("%d", (int) ans);
return 0;
}
給你若干個區間 \([l_i, r_i]\) ,每次可以對乙個區間進行整體異或操作。
區間初始全 \(0\),問你最後可以形成多少種不同的區間。
考慮什麼樣的區間是沒有貢獻的。
假設對於區間 \([l, r]\) ,我們考慮如果存在以下三個區間,那麼這個區間是無用的。
那麼通過不同的組合,有無區間 \([l, r]\) 是沒有意義的。
那麼用並查集維護端點就行了。
#include using namespace std;
const int maxn = 100010;
const int xrz = 1e9 + 7;
const int maxm = (1 << 21);
int n, m, ans = 1, l, r, f[maxn];
int find(int x)
int main()
for(int i = 1; i <= m; ++ i)
f[x] = y;
ans = (ans * 2) % xrz;
} printf("%d", ans);
return 0;
}
一共 \(n\) 天,每天上午會進 \(a_i\) 的物品,中午會有乙個客人想要買走 \(b_i\) 的物品,當然你也可以選擇不買,問你最後最多可以交易多少次。
資料範圍 : \(1 <= n <= 250000, 0 <= a_i, b_i <= 10^9\)
首先,我們看到題目先會想到 \(01\) 揹包。是個正確的作法,但是肯定過不了。
然後,我們考慮到這一定是個貪心/推式子的題目。
但是推式子的題目一般的特性在這裡顯然不符合(推式子的題目一般不會讓你選擇)
那接下來考慮怎麼去貪心。
第一想法是我們選最小的肯定是最優的,因為就算選了這個最小的而導致其他的不可以選,那也最多只能導致乙個不可以選。
因為如果可以導致多個不可以選的話,選了次小的哪乙個也會導致更多的不可以選。
所以選擇最小的策略是對的,\(sort\) 一般的複雜度我們也可以接受,但是問題來了,我們那些數可以取?
取完當前最小的,那麼它前面的一些數說不定不可以再去。
那麼處理這些的複雜度就不穩定了,可以構造資料卡掉。
接下來我們想每天上午進的貨物會對什麼有影響。
這個很顯然,它可以對他後面的所有數產生影響,因為到貨了就可以賣給別人了。
那是不是可以這麼考慮,從後往前去跑,每次去當前可以取的最小的。
因為從後完全就去除了它的後效性,所有正確性也是對的。
但是新增乙個數 \(a_i\) 可能很大,一次可以處理多個數。
那你就必須保證後面整個序列是有序的,而且還要維護乙個字尾和。
我們考慮維護這個有序數列的複雜度最優,那就是往前加乙個數,就把這個數加入到數列裡面去。
這樣的複雜度最劣是 \(o(n^2)\) 的,還是會炸。
那我們是不是無法從一些順序上去找到優化的空間。
我們就可以考慮去莽,然後支援撤銷,這樣也可以保證正確性。
具體的話是這樣實現的:
從前往後讀入,每次可以取就取,並且把這些取過的記錄在單調佇列中。
如果當前這個放不下,我們就把他和佇列首的元素做比較,不斷更新即可。
根據我們的第二個想法,每個前面取過的如果彈出來,因為他的後效性,肯定是可以服務後面的。
那麼就結束了。
#include using namespace std;
#define int long long
const int maxn = 250010;
int n, sum, ans, book[maxn];
priority_queue, vector> > q;
struct node e[maxn];
int cmp(node x, node y)
signed main()
for(int i = 1; i <= n; ++ i)
for(int i = 1; i <= n; ++ i)
else if(! q.empty() && q.top().first > e[i].b)
}printf("%lld\n", ans);
for(int i = 1; i <= n; ++ i)
}return 0;
}
有 \(n\) 個小矮人,每個小矮人有身高 \(a_i\) 和 臂長 \(b_i\)
乙個小矮人可以出去的條件是
\[\sum_^ + b_k >= h
\]問最多可以跑出去多少小矮人。
因為人人平等對吧,所以每個人的價值都是一樣的。
那麼我們就考慮什麼樣的人更加容易出來。
是不是手長+臂長更長的人就更容易出來。
我們考慮有 \(2\) 個人 \(a\) 和 \(\text\) 。
並且 \(\text\) 可以單獨出來,\(\text\) 只可以在 \(a\) 的幫助下出來。
那麼肯定是要先把 \(b\) 放出來,再讓 \(a\) 後出來。
所以我們貪心的策略是把臂長+手長大的放後面。小的先跑出去。
至於我們怎麼實現跑出去的過程,跑一遍最簡單的 \(dp\) 就行了。
#include using namespace std;
const int maxn = 2010;
int n, h, sum, ans, f[maxn];
struct node e[maxn];
int cmp(node x, node y)
int main()
scanf("%d", &h);
sort(e + 1, e + 1 + n, cmp);
for(int i = 1; i <= n; ++ i) }}
for(int i = n; i >= 0; -- i)
}return 0;
}
給你乙個長度為 \(n\) 個字串,存在 \(3\) 種字元:
每個人的行走互不干擾,問你最少過多久才可以取完所有物品。
乍一看就感覺很 \(\text\) .
對每個人 \(\text\) ?
按時間 \(\text\) ?
感覺都不太對,那就不是 \(\text\) 了(大草)
我們考慮怎麼暴力去跑?
先列舉時間,再暴力的找每個人可以取的物品,這樣的複雜度是很恐怖的。
那麼我們先優化時間,對於時間 \(x\) 和 \(x + 1\),如果在 \(x\) 可以取完,那麼 \(x + 1\) 肯定也可以,所以時間是滿足單調性的,可以用二分優化到 \(\text\)
接下來考慮後面這個東西怎麼去 \(\text\) 。
對於每個人,他們可以取完的東西太多了,我們無法有效快速的求。
那我們就考慮對於每乙個物品去找哪個人可以收服他,這樣肯定只有 \(2\) 種決策,他左邊的第乙個人和他右邊的第乙個人。
預處理下就行了。
#includeusing namespace std;
#define mid ((l + r) >> 1)
const int maxn = 200010;
int n, nxt[maxn], ans, l[maxn], r[maxn], lst[maxn], now;
char s[maxn];
bool check(int x)
}for(int i = 1; i <= n; i ++)
if(nxt[i] && l[nxt[i]] < i)
if(nxt[i] == 0 || nxt[i] - i > x)
l[nxt[i]] = i;}}
return 1;
}int main()
else if(s[i] == '*')
}now = 0;
for(int i = n; i ; -- i)
else if(s[i] == '*')
}while(l <= r)
else
} printf("%d", ans);
return 0;
}
algorithm 一些有趣的思維題
hdu 1108 include iostream using namespace std intmain return0 乙個數的任何次方一共只有四種情況,分別列出這四種情況後取餘冪就可以知道尾數是多少。codeforces 1217a include iostream include algor...
資訊學競賽中的一些經典思維 題
倍增字面上意思是 成倍地增加。當模擬乙個過程時,一步一步進行太慢,考慮把模擬的步數二進位制分解 經過一些預處理,每次可以模擬 2 i 步,從而達到優化複雜度的目的。倍增主要模型有rmq,lca等。例題給出乙個長度為 n 的環和乙個常數 k,每次可以從第 i 個點跳到第 i k mod n 1 個點,...
js 的一些題
給出乙個區間 a,b 計算區間內 神奇數 的個數。神奇數的定義 存在不同位置的兩個數字,組成乙個兩位數 且不含前導0 且這個兩位數為質數。比如 153,可以使用數字3和數字1組成13,13是質數,滿足神奇數。同樣153可以找到31和53也為質數,只要找到乙個質數即滿足神奇數。輸入描述 輸入為兩個整數...