A. Removing Columns
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
You are given an n?×?m rectangular table consisting of lower case English letters. In one operation you can completely remove one column from
the table. The remaining parts are combined forming a new table. For example, after removing the second column from the table
abcd edfg hijk
we obtain the table:
acd efg hjk
A table is called good if its rows are ordered from top to bottom lexicographically, i.e. each row is lexicographically no larger than the following one. Determine the minimum number of operations
of removing a column needed to make a given table good.
Input
The first line contains two integers — n and m (1?≤?n,?m?≤?100).
Next n lines contain m small English letters
each — the characters of the table.
Output
Print a single number — the minimum number of columns that you need to remove in order to make the table good.
Sample test(s)
input
1 10 codeforces
output
0
input
4 4 case care test code
output
2
input
5 4 code forc esco defo rces
output
4
Note
In the first sample the table is already good.
In the second sample you may remove the first and third column.
In the third sample you have to remove all the columns (note that the table where all rows are empty is considered good by definition).
Let strings s and t have equal length. Then, s is lexicographically
larger than t if they are not equal and the character following the largest common prefix of s and t (the
prefix may be empty) in s is alphabetically larger than the corresponding character of t.
贪心。
我们可以发现从左往右扫,当前能取的列就一定要取,取了不会更差,只会更好。
什么是能取的列?
在之前所有取好的列中,如果每一列这一行,下一行。。。都相同,那么当前这列的这几行必须满足不减性质,否则任意。
#include <iostream> #include <algorithm> #include <cstring> #include <cstdio> #include <string> #define mp make_pair #define f first #define s second using namespace std; pair<int,int> q[10000],qq[10000]; int n,m,f[105],cnt; string s[105]; int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) cin>>s[i]; int ans=0; cnt=1; q[1]=mp(1,n); for (int i=0;i<m;i++) { int ok=1; for (int j=1;j<=cnt;j++) { for (int k=q[j].f+1;k<=q[j].s;k++) if (s[k][i]<s[k-1][i]) ok=0; if (!ok) break; } if (ok) { ans++; for (int j=1;j<=cnt;j++) qq[j]=q[j]; int c=0; for (int j=1;j<=cnt;j++) { int l=qq[j].f; for (int k=qq[j].f+1;k<=qq[j].s;k++) { if (s[k][i]!=s[k-1][i]) { if (k!=l+1) { q[++c]=mp(l,k-1); } l=k; } } if (l!=qq[j].s) q[++c]=mp(l,qq[j].s); } cnt=c; } } cout<<m-ans<<endl; return 0; }
B. Tennis Game
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
Petya and Gena love playing table tennis. A single match is played according to the following rules: a match consists of multiple sets, each set consists of multiple serves. Each serve is won by one of the players, this player scores one point. As soon as one
of the players scores t points, he wins the set; then the next set starts and scores of both players are being set to 0. As soon as one of the players
wins the total of s sets, he wins the match and the match is over. Here s and t are
some positive integer numbers.
To spice it up, Petya and Gena choose new numbers s and t before
every match. Besides, for the sake of history they keep a record of each match: that is, for each serve they write down the winner. Serve winners are recorded in the chronological order. In a record the set is over as soon as one of the players scores t points
and the match is over as soon as one of the players wins s sets.
Petya and Gena have found a record of an old match. Unfortunately, the sequence of serves in the record isn‘t divided into sets and numbers s and t for
the given match are also lost. The players now wonder what values of s and t might
be. Can you determine all the possible options?
Input
The first line contains a single integer n — the length of the sequence of games (1?≤?n?≤?105).
The second line contains n space-separated integers ai.
If ai?=?1,
then the i-th serve was won by Petya, if ai?=?2,
then the i-th serve was won by Gena.
It is not guaranteed that at least one option for numbers s and t corresponds
to the given record.
Output
In the first line print a single number k — the number of options for numbers s and t.
In each of the following k lines print two integers si and ti —
the option for numbers s and t. Print the options
in the order of increasing si,
and for equal si —
in the order of increasing ti.
Sample test(s)
input
5 1 2 1 2 1
output
2 1 3 3 1
input
4 1 1 1 1
output
3 1 4 2 2 4 1
input
4 1 2 1 2
output
0
input
8 2 1 2 1 1 1 1 1
output
3 1 6 2 3 6 1
对于一个t来说,s是唯一的,因此我们可以枚举t,然后判断多少回合会赢。
记录第k个1/2出现的位置,以及到每个位置共有1几个1和几个2出现过。
只要判断谁先得到t分就知道这一回合谁赢了,往后枚举即可。
这样看起来很暴力,但是n/1+n/2+n/3+n/4+......的复杂度是O(nlogn)的!
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cstring> #define mp make_pair #define inf 0x3f3f3f3f #define M 200005 using namespace std; int s1[M],s2[M],x[M],p1[M],p2[M],n; pair<int,int> ans[M]; int Judge(int t) { int k1=0,k2=0,now=0; while (now<n) { if (p1[s1[now]+t]<p2[s2[now]+t]) k1++,now=p1[s1[now]+t]; else k2++,now=p2[s2[now]+t]; if (now>n) return 0; } if (k1>k2) return k1; return 0; } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) scanf("%d",&x[i]); memset(p1,127,sizeof(p1)); memset(p2,127,sizeof(p2)); if (x[n]==2) for (int i=1;i<=n;i++) x[i]=3-x[i]; int n1=0,n2=0; for (int i=1;i<=n;i++) { if (x[i]==1) p1[++n1]=i; else p2[++n2]=i; s1[i]=n1,s2[i]=n2; } int cnt=0; for (int i=1;i<=n;i++) { int k=Judge(i); if (k) ans[++cnt]=mp(k,i); } sort(ans+1,ans+1+cnt); cout<<cnt<<endl; for (int i=1;i<=cnt;i++) printf("%d %d\n",ans[i].first,ans[i].second); return 0; }
C. Distributing Parts
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
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, ci and 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 thej-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!
Input
The first line contains a single integer n — the number of parts in the play (1?≤?n?≤?105).
Next n lines contain two space-separated integers each, aj and bj —
the range of notes for the j-th part (1?≤?aj?≤?bj?≤?109).
The next line contains a single integer m — the number of actors (1?≤?m?≤?105).
Next m lines contain three space-separated integers each, ci, di and ki —
the range of the i-th actor and the number of parts that he can perform (1?≤?ci?≤?di?≤?109, 1?≤?ki?≤?109).
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).
Sample test(s)
input
3 1 3 2 4 3 5 2 1 4 2 2 5 1
output
YES 1 1 2
input
3 1 3 2 4 3 5 2 1 3 2 2 5 1
output
NO
贪心+STL。
这题也要想的清清楚楚再写。。
(以下l表示下界,r表示上界)
我们首先把part和actor都按照l排序,枚举part,然后把所有l不大于这个part的l都插入set中,贪心的选择r大于等于这个part的r的最小r,然后k--,如果这个actor的k=0,那么从set中除去。
#include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm> #include <cmath> #include <set> #define mp make_pair using namespace std; set<pair<int,int> > s; set<pair<int,int> >::iterator it; int n,m,ans[100005]; struct data { int l,r,k,id; }a[100005],b[100005]; bool cmp(data a,data b) { if (a.l==b.l) return a.r<b.r; return a.l<b.l; } int main() { scanf("%d",&n); for (int i=1;i<=n;i++) a[i].id=i,scanf("%d%d",&a[i].l,&a[i].r); scanf("%d",&m); for (int i=1;i<=m;i++) b[i].id=i,scanf("%d%d%d",&b[i].l,&b[i].r,&b[i].k); sort(a+1,a+1+n,cmp); sort(b+1,b+1+m,cmp); int j=1; for (int i=1;i<=n;i++) { for (;j<=m&&b[j].l<=a[i].l;j++) s.insert(mp(b[j].r,j)); it=s.lower_bound(mp(a[i].r,0)); if (it==s.end()) { puts("NO"); return 0; } int x=it->second; ans[a[i].id]=b[x].id; b[x].k--; if (!b[x].k) s.erase(mp(b[x].r,x)); } cout<<"YES"<<endl; cout<<ans[1]; for (int i=2;i<=n;i++) cout<<" "<<ans[i]; cout<<endl; return 0; }