C-Messenger in MAC
題意:
即輸入n個pair<int,int> [a,b],任意選擇0個或多個arri,使得式子值小於等於K的情況下,最多可以選幾個不同的i。i可以不連續.可以只選一個點,但不可以重複選一個點。
做法:思維。可以發現按b從小到大排序之後,b部分計算的值為br-bl.因此可以按照b從小到大排序,列舉l,r。o(n*n),4e6.
因為確定了l,r那麼l,r之間的 i 無論怎麼選,b的值都不會改變。此時只需要考慮a的值。需要用的是大根堆,存放每次固定l時,從l到r的所有a的值,一旦a太大,直接pop,
因為後面的br-bl(bl固定,br增大)會更大。此時不滿足,後面更加不會滿足。
??疑惑的關鍵點:
""如果彈出的是中間的值,那麼就無所謂,反正本來所選的部分就不用連續,但是如果彈出了左右邊界,那麼我們維護的br-bl豈不是失效了,假設我們真的彈出了左右邊界,那麼當前的左邊界應該是l+c,右邊界應該是r-d,這個區間我們在設定左邊界為l+c的時候會遍歷到,而且因為區間縮小了,左右邊界更近了,所以實際的br-bl可能會變小,這裡用一個更大的值來表示,不會多算,但是卻可以幫我們訪問所有的情況。顯然區間固定的時候,彈出較大的a是可行的策略。""--csdn-as_sun的題解
#include<bits/stdc++.h>
using namespace std;
#define int long long
bool cmp(pair<int,int> a,pair<int,int> b){
return a.second<b.second;
}
void solve(){
int n,k,ans=0;
cin>>n>>k;
pair<int,int> arr[2003];
for(int i=1;i<=n;i++) cin>>arr[i].first>>arr[i].second;
sort(arr+1,arr+n+1,cmp);
for(int i=1;i<=n;i++){ //7 8 17 22 28
//priority_queue<int,vector<int>,greater<int> > pq; //greater是小根堆
priority_queue<int> pq; //預設是大根堆
int sum=0,last=0;
for(int j=i;j<=n;j++){
sum-=last; //減去上一組的br-bl的值
sum+=arr[j].second-arr[i].second;
last=arr[j].second-arr[i].second;
pq.push(arr[j].first);
sum+=arr[j].first;
// priority_queue<int,vector<int>,greater<int> > pq0=pq; //因為b是從小到大排序,所以如果前面的pq.top()已經太大了,後面肯定更加用不上,可以直接pop()
while(pq.size()&&sum>k){
sum-=pq.top();
pq.pop();
}
ans=max(ans,(int)pq.size());
}
}
cout<<ans<<"\n";
}
signed main(){
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int t=1;
cin>>t;
while(t--){
solve();
}
return 0;
}
D-Exam in MAC
題意:
做法:見程式碼註釋。
void solve(){ //容斥,正難則反
//合法的pair有很多,那麼我們可以反正做.直接算出所有組合的ans,再減去不合法的組合(y+x)的個數和(y-x)的個數.
//但是這樣是多減了一部分,那麼ans需要加上同時滿足(y+x)不合法且(y-x)也不合法的個數.
//y+x和y-x不合法的個數容易計算,但是同時不合法的應該怎麼計算?
//設y+x=ai;
// y-x=aj;
//那麼有:x=(ai-aj)/2;
// y=(ai+aj)/2;
//因為選擇組成pair的值都是整數,那麼(ai-aj)和(ai+aj)都必須是2的倍數,且ai>=aj!!;
//即ai,aj同奇或同偶;
//那麼只需要數出輸入的數之中odd的個數和even的個數,然後進行兩兩組合即可(ai>=aj).
//不用擔心組合會不會是不存在的,因為所選的ai和aj都是來自輸入的數字,並且是同奇偶的.那麼總是有組合x,y是可以同時滿足y+x=ai,y-x=aj.
int n,c,arr[300005],ans=0;
cin>>n>>c;
ans=(c+1)*(1+c+1)/2;
int cntodd=0,cnteven=0;
for(int i=1;i<=n;i++) {
cin>>arr[i];
if(arr[i]&1) cntodd++;
else cnteven++;
ans-=(arr[i]/2)+1; //y+x
ans-=c-arr[i]+1; //y-x
}
ans+=cntodd*(cntodd+1)/2;
ans+=cnteven*(cnteven+1)/2;
cout<<ans<<endl;
}