【JZOJ7045】数学考试
【JZOJ7045】数学考试
by AmanoKumiko
Description
8:00,学校,数学教室 这 tmd 这么水?蒟蒻 steven 看着数学考试卷子感到困惑。 这不是这样再这样再那样就做完了吗? 于是 ta 奋笔疾书,花了一场考试勉强写完了卷子。(就这?? 8:50,下课后 5min “?????我错了这么多?????”蒟蒻 steven 大惑不解。 “你这里做的太麻烦了,就你这算错很正常。还有这里,阴沟翻船。还有……”数学老师认 真的喷着蒟蒻 steven。 steven 虽然很不爽,但是没办法,考的不好就只能服软。 16:30,学校,机房 “关于数学考试总是把问题想得很麻烦而做错这档事,108oahnew 学姐有什么办法解决吗?” “az,我觉得……”108oahnew 刚想说话,Wu_Mr 就凑了上来。 “那就多练练这种计算嘛,算不错多麻烦也没问题了。” “我 ** 你个 ** ,你这样真的能帮到 ta 吗?” “那 Wu_Mr 学姐该怎么练呢?” “来 gartic.io 吧,多玩玩这个就可以了。” “????”蒟蒻 steven 和 108oahnew 都感到疑惑。 “用这个东西我来给你画点题嘛。然后你不用草稿纸来口算,这样不就能好了嘛。” “那好吧,学姐来画吧。” 几天后的数学课 在经过 Wu_Mr 几天的《训练》之后,steven 感觉自己已经不当人了。 又是一次考试,这次 steven 将问题都转化成了求几个函数的和的最大值,不过每个函数的 自变量的取值是有很多限制的(具体见输入格式)。 然后不出意外的,steven 又死了。 在老师发答案之前,ta 想知道答案到底是多少,于是 ta 想写个程序来帮助 ta 求出正确的 答案。
Input
先输入一个数 T 表示考试题数。 对于每道题, 第一行两个整数 n, m。表示列出来的要求的函数的个数和限制数。 接下来 n 行,第 i 行 6 个数 ai , bi , ci , di , Li , Ri。 这 6 个数分别为函数的系数\(f(xi)=aix^3_i+bix^2_i+cixi + di\)和 xi 的取值范围,即 xi 只能 取\([Li , Ri ]\)的整数。 接下来 m 行,每行 3 个数 u, v, D ,表示 xu ≤ xv + D。
Output
对于每场考试,输出一个数,若有解则输出满足条件的 \(∑^n_{i=1}f(xi)\) 的最大值,无解则输出 “mei ji ge”(不包含引号)。 每个结果占一行。
Sample Input
1
2 2
0 0 1 0 −10 10
0 0 −1 0 90 100
2 1 80
1 2 100
Sample Output
−80
Data Constraint
对于 100% 的数据,|ai | ≤ 5, |bi | ≤ 100, |ci | ≤ 100, |di | ≤ 100, n ≤ 100, m ≤ 500, |Li | ≤ 100, |Ri | ≤ 100, |Di | ≤ 100。 对于 100% 的数据,T ≤ 5。
Solution
《看到奇怪的数据范围可以考虑网络流》
若没有限制
则直接对每个点从源点到汇点连一条长度为\(r-l+1\)的链,边权为对应的函数值
然后割掉一条边即为这个x选择这个值
故直接求最小割
对于每个限制\(xu ≤ xv + D\)
转化成\(xv≥xu-D\)
即当\(u\)取\(xu\)时,\(v\)最小取\(xu-D\)
故对于\(u\)链上的点,向其对应的\(v\)上的\(xu-D\)连一条边权为\(inf\)的边
Code
#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(register int i=a;i<=b;i++)
#define Fd(i,a,b) for(register int i=a;i>=b;i--)
#define Fs(i,a) for(register int i=cur[a];i;i=e[i].next)
#define I 9223372036854775807
#define inf 100000000000000
#define LL long long
#define N 110
#define P N*200
LL D,ans;
int T,n,m,u,v,s,t,tot,cnt,cur[P],gap[P],dis[P],last[P],num[N][N*2];
struct node{int en;LL v;int next;}e[300010];
struct mode{LL a,b,c,d,L,R;}fx[N];
LL cube(LL x){return x*x*x;}
LL sqr(LL x){return x*x;}
LL calc(LL x,int pos){return fx[pos].a*cube(x)+fx[pos].b*sqr(x)+fx[pos].c*x+fx[pos].d;}
void add(int a,int b,LL c){e[++tot]=(node){b,c,last[a]};last[a]=tot;}
LL dfs(int now,LL flow){
if(now==t)return flow;
LL have=0;
Fs(i,now)if(e[i].v&&dis[e[i].en]+1==dis[now]){
cur[now]=i;
LL tmp=dfs(e[i].en,min(flow-have,e[i].v));
e[i].v-=tmp;e[i^1].v+=tmp;have+=tmp;
if(have==flow)return flow;
}
cur[now]=last[now];
if(!(--gap[dis[now]]))dis[0]=P;
++gap[++dis[now]];
return have;
}
int main(){
freopen("sleep.in","r",stdin);
freopen("sleep.out","w",stdout);
scanf("%d",&T);
while(T--){
bool flag=0;
ans=s=t=0;tot=1;
memset(last,0,sizeof(last));
memset(gap,0,sizeof(gap));
memset(dis,0,sizeof(dis));
memset(cur,0,sizeof(cur));
scanf("%d%d",&n,&m);
F(i,1,n)scanf("%lld%lld%lld%lld%lld%lld",&fx[i].a,&fx[i].b,&fx[i].c,&fx[i].d,&fx[i].L,&fx[i].R);
F(i,1,n) F(j,fx[i].L,fx[i].R)num[i][j+100]=++t;t++;
F(i,1,n){
add(s,num[i][fx[i].L+100],I);add(num[i][fx[i].L+100],s,0);
F(j,fx[i].L,fx[i].R-1){
add(num[i][j+100],num[i][j+101],inf-calc(j,i));
add(num[i][j+101],num[i][j+100],0);
}
add(num[i][fx[i].R+100],t,inf-calc(fx[i].R,i));add(t,num[i][fx[i].R+100],0);
}
F(i,1,m){
scanf("%d%d%lld",&u,&v,&D);
F(j,fx[u].L,fx[u].R){
if(fx[v].L<=j-D&&j-D<=fx[v].R){
add(num[u][j+100],num[v][j-D+100],I);
add(num[v][j-D+100],num[u][j+100],0);
}else
if(j-D>fx[v].R){
add(num[u][j+100],t,I);
add(t,num[u][j+100],0);
}
}
}
gap[0]=t+1;
while(dis[0]<P){LL q=dfs(0,I);ans+=q<I?q:0;}
ans=inf*n-ans;
if(ans>1145141145||ans<-1145141145)printf("mei ji ge\n");
else printf("%lld\n",ans);
}
return 0;
}