#include<iostream>#include<cstdio>#include<cmath>#include<algorithm>#include<map>
using namespace std;#define ll long long #define db double#define INF 0x3f3f3f3fconstint mxn =2005;int n, k;struct Node
{
db a, b;int x;int sum;
bool operator <(const Node z)const{if(sum == z.sum)return x < z.x;return sum > z.sum;}} st[mxn];
db mrk[mxn][mxn];
db ar[mxn], arr[mxn];int brr[mxn];//统计每个队伍的数量char c[2];intmain(){/* freopen("A.txt", "r", stdin); *//* freopen("Ans.txt", "w", stdout); */scanf("%d %d",&n,&k);for(int i =1; i <= n; i ++){scanf("%lf %s",&st[i].a, c), st[i].a *=0.6;
st[i].x = c[0]-'A'+1;}for(int i =1; i <= k; i ++){for(int j =1; j <= k; j ++)scanf("%lf",&mrk[i][j]), ar[j]+= mrk[i][j];}for(int i =1; i <= k; i ++){
ar[i]/= k;}for(int i =1; i <= k; i ++){for(int j =1; j <= k; j ++){if(mrk[i][j]>= ar[j]-15&& mrk[i][j]<= ar[j]+15)
arr[j]+= mrk[i][j], brr[j]++;}}for(int i =1; i <= k; i ++){
arr[i]=round(arr[i]/brr[i]);}for(int i =1; i <= n; i ++){
st[i].b = arr[st[i].x]*0.4;
st[i].sum =round(st[i].a + st[i].b);}sort(st +1, st +1+ n);for(int i =1; i <= n; i ++){printf("%d %c\n", st[i].sum, st[i].x +'A'-1);}return0;}
那么我们可以从题意上找出隐含的不等式,如果 当前同学(v 为其橘子的数量)的分数 == 左边同学(u 为其橘子的数量)的分数的,那么说明 v == u, 那么我们建立权值为为0的双向边,如果分高于的话v - u >= 1 建立 i-1 -> i 权值为1 的边,如果分低于的话那么 u - v >= 1,建立 i -> i -1 权值为1的反向边
代码(贪心)
#include<iostream>#include<cstdio>#include<algorithm>#include<string>#include<map>#include<cstring>
using namespace std;#define ll long long constint mxn =1e6+10;int ar[mxn];
ll br[mxn];intmain(){/* freopen("A.txt","r",stdin); *//* freopen("Ans.txt","w",stdout); */int n;scanf("%d",&n);for(int i =1; i <= n; i ++)scanf("%d",&ar[i]), br[i]=1;for(int i =2; i <= n; i ++){if(ar[i]> ar[i -1])
br[i]= br[i -1]+1;elseif(ar[i]== ar[i -1])
br[i]= br[i -1];}for(int i = n -1; i >=1; i --){if(ar[i]> ar[i +1]&& br[i]<= br[i +1])
br[i]= br[i +1]+1;elseif(ar[i]== ar[i +1])
br[i]=max(br[i], br[i +1]);}
ll sum =0;for(int i =1; i <= n; i ++)
sum += br[i];printf("%lld\n", sum);return0;}
代码(最长路-差分约束)
#include<iostream>#include<cstdio>#include<cmath>#include<algorithm>#include<map>#include<queue>
using namespace std;#define ll long long #define db double#define INF 0x3f3f3f3fconstint mxn =1e6+10;int ar[mxn];int n;struct Edge
{int v, w, next;} edge[mxn *4];int head[mxn];int k =0;struct Node
{int x, dis;
bool operator <(const Node a)const{return dis < a.dis;}};voidAdd(int u,int v,int w){
edge[++ k]=(Edge){ v, w, head[u]};
head[u]= k;}int dis[mxn], use[mxn];voidSpfa(int s){for(int i =0; i <= n; i ++)
dis[i]=-INF, use[i]=0;
dis[s]=0;
priority_queue<Node> q;
q.push((Node){ s, dis[s]});int u, v, w;while(! q.empty()){
u = q.top().x; q.pop();
use[u]=0;for(int i = head[u]; i; i = edge[i].next){
v = edge[i].v;
w = edge[i].w;if(dis[v]< dis[u]+ w){
dis[v]= dis[u]+ w;if(! use[v]){
q.push((Node){ v, dis[v]});
use[v]=1;}}}}}intmain(){/* freopen("A.txt", "r", stdin); *//* freopen("Ans.txt", "w", stdout); */scanf("%d",&n);for(int i =1; i <= n; i ++)scanf("%d",&ar[i]);for(int i =2; i <= n; i ++){if(ar[i]== ar[i -1]){Add(i-1, i,0);Add(i, i-1,0);}elseif(ar[i]> ar[i -1]){Add(i-1, i,1);// v >= 1 + u}else{Add(i, i-1,1);// u - v >= 1; u >= v + 1}/* if(ar[i] == ar[i + 1]) *//* { *//* Add(i, i+1, 0); *//* Add(i+1, i, 0); *//* } *//* else if(ar[i] > ar[i + 1]) *//* { *//* Add(i+1, i, 1); *//* } *//* else *//* { *//* Add(i, i+1, 1); *//* } */}for(int i =1; i <= n; i ++){Add(0, i,1);}Spfa(0);
ll sum =0;for(int i =1; i <= n; i ++)
sum += dis[i];printf("%lld\n", sum);return0;}
现在我们考虑开头的两种情况:反转开头2位 、反转开头连续的3位,我们对两种情况分别进行,尝试翻转就行了,显然这两种情况都有可能反转出符合题意的状态,但是可能的反转的次数不一样,这个时候我们去反转的次数小的那个数就行了,如果只有一个能反转出全0状态,那就输出那个结果,如果都不能反转出全0状体,输出 No