D:
題目大意:兩個人進行比賽,我們只知道進行了N局比賽的結果,N局之後有一個人贏得了最終的比賽。1代表第一個人贏,2代表第二個人贏。給你他們的輸贏情況,讓你求出來怎麼安排比賽才能得到這種情況,輸出時,先按S排序,如果S相同按照T排序。按順序輸出所有的S,T。
思路:我們可以預處理出來在第幾的位置某個人贏了x場。
比如:
8
2 1 2 1 1 1 1 1
我們需要列舉贏k場比賽算贏了一小場,注意最後贏的人一定必須是這一局的勝利者。
列舉k之後我們從0開始向後找比如k = 2, xpos代表1贏k場的位置,ypos代表2贏k場的位置。我們找到xpos = 4,ypos = 3,所以如果贏兩次算贏一小局的話,2贏下了第一小局。之後2要找贏的兩場之後的位置就是sum2=y+k的位置,此時沒有,1要找1+k的位置(因為在2贏下一小局的時候1的有一小節是不再被帶到下一小局的,所以他如果贏的下一小局的話,就要找到x(到勝負確定的位置時,已經有幾小節1結束了)+k(下一次要贏的次數)的位置)。此時xpos
= 5,依此類推下去。。。但是需要注意的是在最後一次的比賽的時候1要解決這一小局的比賽,但是k=2時,顯然1結局不了最後一局,所以k = 2,不滿足條件。
這裡找到下一次x+k或者y+k的位置是可以用二分列舉字首和,也可以hash處理出來所有的和,O(1)的尋找。
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <time.h>
#include <map>
#include <set>
#define eps 1e-8
#define M 1000100
#define LL long long
//#define LL long long
#define INF 0x3f3f3f
#define PI 3.1415926535898
#define read() freopen("data1.in", "r", stdin)
#define write() freopen("data1.out", "w", stdout);
const int maxn = 200010;
using namespace std;
int sum1[maxn];
int sum2[maxn];
struct node
{
int sum, pos;
int flag;
};
node f[maxn], p[maxn];
struct N
{
int x, y;
} fx[maxn];
bool cmp(N a, N b)
{
if(a.x == b.x) return a.y < b.y;
return a.x < b.x;
}
int num[maxn];
int main()
{
int n;
while(cin >>n)
{
for(int i = 1; i <= n; i++) scanf("%d",&num[i]);
int cnt = 0;
sum1[0] = 0;
sum2[0] = 0;
for(int i = 1; i <= n; i++)
{
f[i].flag = p[i].flag = 0;
f[i].pos = p[i].pos = 0;
if(num[i] == 1)
{
sum1[i] = sum1[i-1]+1;
sum2[i] = sum2[i-1];
continue;
}
sum1[i] = sum1[i-1];
sum2[i] = sum2[i-1]+1;
}
for(int i = n; i >= 1; i--)
{
f[sum1[i]].pos = i;
f[sum1[i]].sum = sum1[i];
f[sum1[i]].flag = 1;
p[sum2[i]].pos = i;
p[sum2[i]].sum = sum2[i];
p[sum2[i]].flag = 1;
}
///for(int i = 1; i <= n; i++) cout<<num[n]<<endl;
for(int i = 1; i <= n; i++)
{
int x = 0;
int y = 0;
int xsum1 = 0;
int xsum2 = 0;
int xx = 0, yy = 0;
int xflag = 0;
while(x < n && y < n)
{
///cout<<x<<" "<<y<<endl;
int xpos = 0;
int ypos = 0;
if(f[x+i].flag) xpos = f[x+i].pos;
if(p[y+i].flag) ypos = p[y+i].pos;
if(!xpos && !ypos) break;
if(xpos && ypos)
{
if(xpos < ypos)
{
xsum1++;
x = sum1[xpos];
y = sum2[xpos];
xx = xpos;
}
else
{
xsum2++;
x = sum1[ypos];
y = sum2[ypos];
xx = ypos;
}
}
else if(xpos)
{
xsum1++;
x = sum1[xpos];
y = sum2[xpos];
xx = xpos;
}
else if(ypos)
{
xsum2++;
x = sum1[ypos];
y = sum2[ypos];
xx = ypos;
}
}
if(xflag) continue;
if(xx != n ) continue;
if(xsum1 > xsum2 && (num[n] == 1))
{
fx[cnt].x = xsum1;
fx[cnt++].y = i;
}
else if(xsum2 > xsum1 && (num[n] == 2))
{
fx[cnt].x = xsum2;
fx[cnt++].y = i;
}
}
sort(fx, fx+cnt, cmp);
cout<<cnt<<endl;
for(int i = 0; i < cnt; i++) cout<<fx[i].x<<" "<<fx[i].y<<endl;
}
return 0;
}
</span>
E:和上海區域賽的題目好像,當時滿滿的都是淚啊,sad。。。
整體來說就是一個按照邊界排序後的貪心,需要用到STL。
題目大意:每個人都有一個音域,而每個樂隊對音域的要求不一樣,每個樂隊還有一個人數限制,讓你把所有的人都安排到樂隊當中求,如果安排不下輸出“NO”否則輸出“YES”,並且輸出每個人屬於哪個樂隊。
思路:人的聲音音域,和樂隊的要求按照右邊r排序,然後列舉每個樂隊,把符合的人都送進set裡面去,然後找k次,二分set裡面的左邊l,如果滿足l1 >= l2的話說明包含在裡面就記錄一下然後從set裡面丟出來。
You are an assistant director in a new musical play. The play consists of n musical parts, each part must be performed by exactly one actor.
After the casting the director chose m actors who can take part in the play. Your task is to assign the parts to actors. However, there are several limitations.
First, each actor has a certain voice range and there are some parts that he cannot sing. Formally, there are two integers for each actor, ciand di (ci ≤ di) —
the pitch of the lowest and the highest note that the actor can sing. There also are two integers for each part — aj and bj(aj ≤ bj) —
the pitch of the lowest and the highest notes that are present in the part. The i-th actor can perform the j-th
part if and only if ci ≤ aj ≤ bj ≤ di,
i.e. each note of the part is in the actor's voice range.
According to the contract, the i-th actor can perform at most ki parts.
Besides, you are allowed not to give any part to some actors (then they take part in crowd scenes).
The rehearsal starts in two hours and you need to do the assignment quickly!
Output
If there is an assignment that meets all the criteria aboce, print a single word "YES" (without the quotes) in the first line.
In the next line print n space-separated integers. The i-th
integer should be the number of the actor who should perform the i-th part. If there are multiple correct assignments, print any of them.
If there is no correct assignment, print a single word "NO" (without the quotes).
#include <algorithm>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <iomanip>
#include <stdio.h>
#include <string>
#include <queue>
#include <cmath>
#include <stack>
#include <time.h>
#include <map>
#include <set>
#define eps 1e-8
#define M 1000100
#define LL long long
//#define LL long long
#define INF 0x3f3f3f
#define PI 3.1415926535898
#define read() freopen("data1.in", "r", stdin)
#define write() freopen("data1.out", "w", stdout);
const int maxn = 200010;
using namespace std;
struct node
{
LL l, r, k;
LL pos, ans;
bool operator < (const node & b) const
{
if(r == b.r) return l < b.l;
return r < b.r;
}
};
node f[maxn], p[maxn];
bool cmp(node a, node b)
{
return a.pos < b.pos;
}
struct Point
{
LL l, r, pos;
bool operator < (const Point& b) const
{
if(l == b.l)
{
if(r == b.r) return pos < b.pos;
return r < b.r;
}
return l < b.l;
}
};
int n, m;
int main()
{
ios::sync_with_stdio(false);
while(cin >>n)
{
for(int i = 0; i < n; i++)
{
cin >>f[i].l>>f[i].r;
f[i].pos = i;
}
cin >>m;
for(int i = 0; i < m; i++)
{
cin >>p[i].l>>p[i].r>>p[i].k;
p[i].pos = i;
}
sort(f, f+n);
sort(p, p+m);
///for(int i = 0; i < m; i++) cout<<p[i].l<<" "<<p[i].r<<endl;
set<Point> s;
int cnt = n;
for(int i = 0, j = 0; i < m; i++)
{
while(j < n && f[j].r <= p[i].r)
{
s.insert((Point){f[j].l, f[j].r, j});
j++;
}
for(int sj = 0; sj < p[i].k; sj++)
{
set< Point >::iterator it;
it = s.lower_bound((Point){p[i].l, 0, 0});
if(it == s.end()) break;
f[it->pos].ans = p[i].pos+1;
s.erase(it);
cnt--;
}
}
if(s.size()!=0 || cnt)
{
cout<<"NO"<<endl;
continue;
}
sort(f, f+n, cmp);
cout<<"YES"<<endl;
for(int i = 0; i < n-1; i++) cout<<f[i].ans<<" ";
cout<<f[n-1].ans<<endl;
}
return 0;
}
</span>