10.16模拟赛(湖南集训)
题解:二分答案。
二分OP最后相交的直线。
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 500010 using namespace std; int n,m,l,r,mid,xp,yp; int zx[maxn],zy[maxn]; inline int read(){ char ch=getchar();int x=0,f=1; for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0'; return x*f; } bool check(int k){ double kk; kk=-1.*zy[k]/(1.*zx[k]); /*kk*1.0*xp<<" "<<1.0*zy[k]不知道为什么直接相加某个数据是22e..+...,非要开新变量a,b存*/ long double a=kk*1.0*xp,b=1.0*zy[k]; // cout<<a<<" "<<b<<endl; // cout<<a+b<<endl; return (1.*yp)>=(long double)(a+b); } int main(){ freopen("geometry.in","r",stdin); freopen("geometry.out","w",stdout); n=read(); for(int i=1;i<=n;i++)zx[i]=read(); for(int i=1;i<=n;i++)zy[i]=read(); sort(zx+1,zx+n+1);sort(zy+1,zy+n+1); m=read(); while(m--){ xp=read();yp=read(); l=1;r=n;int ans=0; while(l<=r){ mid=(l+r)>>1; if(check(mid)){ ans=mid; l=mid+1; }else r=mid-1; } printf("%d\n",ans); } fclose(stdin);fclose(stdout); return 0; }
题解:差分约束
(目前不是很理解差分约束最大最小值什么的..但是思路还是会的。
毕竟以前也做过差分约束的裸题...)
设s[i]前0-i时刻一共安排了多少个人..就是前缀和。
有这么几个约束条件。
s[i]-s[i-1]>=0(都前缀和了,肯定大于等于0啊
s[i]-s[i-1]<=b[i](题目说了,你就有这b[i]个人愿意在i上。
这两个条件是显然的啦,还有几个约束条件,就是题目中说的必须要安排大于等于a[i]个人在i-i+1
i是时刻。
当i>=8时,s[i]-s[i-8]>=a[i]。如果要求红色位置的人,也就是8-9的人大于等于a[i](a[8]),那么
1--8在职的人数必须大于等于a[i],也就是覆盖蓝色部分的人数和必须>=a[i]。蓝色的格子,发现
在任意一个蓝色格子的左端点安排人,都会覆盖红色格子。
所以s[i]-s[i-8]>=a[i].
当i<8时,s[23]-s[16+i]+s[i]>=a[i];(下标从0开始)。
蓝色格子同上。
但是最后一个式子不满足差分约束的形式,但我们发现s[23]是常量,也就是我们所求的答案,
是具有单调性的。可以二分,也可以从小到大枚举,第一个满足条件的就是答案喽。
然后跑spfa,没有解的条件是有负环。
代码:
#include<iostream> #include<cstdio> #include<queue> #include<algorithm> #include<cstring> #define maxn 50 using namespace std; queue<int>q; int sumedge,ans,t; int head[maxn],a[maxn],b[maxn]; int dis[maxn],vis[maxn]; struct Edge{ int x,y,z,nxt; Edge(int x=0,int y=0,int z=0,int nxt=0): x(x),y(y),z(z),nxt(nxt){} }edge[maxn<<1]; void add(int x,int y,int z){ edge[++sumedge]=Edge(x,y,z,head[x]); head[x]=sumedge; } bool spfa(){ memset(vis,0,sizeof(vis)); memset(dis,-0x3f,sizeof(dis)); while(!q.empty())q.pop(); q.push(0);dis[0]=0;vis[0]=1; while(!q.empty()){ int now=q.front();q.pop();vis[now]=false; if(dis[now]>1000)return false; for(int i=head[now];i;i=edge[i].nxt){ int v=edge[i].y; if(dis[v]<dis[now]+edge[i].z){ dis[v]=dis[now]+edge[i].z; if(!vis[v]){ vis[v]=true; q.push(v); } } } } return true; } bool check(int ans){ memset(head,0,sizeof(head));sumedge=0; for(int i=9;i<=24;i++)add(i-8,i,a[i]); for(int i=1;i<=8;i++)add(i+16,i,a[i]-ans); for(int i=1;i<=24;i++){ add(i-1,i,0);add(i,i-1,-b[i]); } add(0,24,ans);add(24,0,-ans); return spfa(); } int main(){ scanf("%d",&t); while(t--){ for(int i=1;i<=24;i++)scanf("%d",&a[i]); for(int i=1;i<=24;i++)scanf("%d",&b[i]); ans=0; while(1){ if(++ans>1000){ ans=-1; break; } if(check(ans))break; } cout<<ans<<endl; } }
std:
#include <cstdio> #include <cstdlib> #define MOD 1000000007 #define N 100005 typedef long long LL; using namespace std; struct Node { LL f[11]; }node[N * 4]; LL a[N], lazy1[N * 4]; bool lazy2[N * 4]; LL C[N][11]; Node merge(Node lc, Node rc) { Node o; o.f[0] = 1; for (int i = 1; i <= 10; i++) { o.f[i] = 0; for (int j = 0; j <= i; j++) o.f[i] = (o.f[i] + lc.f[j] * rc.f[i - j] % MOD) % MOD; } return o; } void build(int o, int l, int r) { if (l == r) { for (int i = 0; i <= 10; i++) node[o].f[i] = 0; node[o].f[0] = 1; node[o].f[1] = (a[l] % MOD + MOD) % MOD; return ; } int mid = (l + r) >> 1; build(o * 2, l, mid); build(o * 2 + 1, mid + 1, r); node[o] = merge(node[o * 2], node[o * 2 + 1]); return ; } void update1(int o, int l, int r, int c) { int len = r - l + 1; LL ff[11]; for (int i = 0; i <= 10; i++) ff[i] = node[o].f[i]; for (int i = 1; i <= 10; i++) { node[o].f[i] = 0; LL t = 1; for (int j = 0; j <= i; j++) { LL tmp = ff[i - j] * C[len - (i - j)][j] % MOD * t % MOD; node[o].f[i] = (node[o].f[i] + tmp) % MOD; t = t * c % MOD; } } return ; } void push_down(int o, int l, int r) { int mid = (l + r) >> 1; if (lazy1[o]) { if (lazy2[o * 2]) lazy1[o * 2] = (lazy1[o * 2] + MOD - lazy1[o]) % MOD; else lazy1[o * 2] = (lazy1[o * 2] + lazy1[o]) % MOD; if (lazy2[o * 2 + 1]) lazy1[o * 2 + 1] = (lazy1[o * 2 + 1] + MOD - lazy1[o]) % MOD; else lazy1[o * 2 + 1] = (lazy1[o * 2 + 1] + lazy1[o]) % MOD; update1(o * 2, l, mid, lazy1[o]); update1(o * 2 + 1, mid + 1, r, lazy1[o]); lazy1[o] = 0; } if (lazy2[o]) { lazy2[o * 2] ^= 1; lazy2[o * 2 + 1] ^= 1; for (int j = 1; j <= 10; j += 2) { node[o * 2].f[j] = MOD - node[o * 2].f[j]; node[o * 2 + 1].f[j] = MOD - node[o * 2 + 1].f[j]; } lazy2[o] = 0; } } void modify1(int o, int l, int r, int ll, int rr, int c) { if (ll <= l && rr >= r) { if (lazy2[o]) lazy1[o] = (lazy1[o] + MOD - c) % MOD; else lazy1[o] = (lazy1[o] + c) % MOD; update1(o, l, r, c); return ; } int mid = (l + r) >> 1; push_down(o, l, r); if (ll <= mid) modify1(o * 2, l, mid, ll, rr, c); if (rr > mid) modify1(o * 2 + 1, mid + 1, r, ll, rr, c); node[o] = merge(node[o * 2], node[o * 2 + 1]); return ; } void modify2(int o, int l, int r, int ll, int rr) { if (ll <= l && rr >= r) { for (int i = 1; i <= 10; i += 2) node[o].f[i] = MOD - node[o].f[i]; lazy2[o] ^= 1; return ; } int mid = (l + r) >> 1; push_down(o, l, r); if (ll <= mid) modify2(o * 2, l, mid, ll, rr); if (rr > mid) modify2(o * 2 + 1, mid + 1, r, ll, rr); node[o] = merge(node[o * 2], node[o * 2 + 1]); return ; } Node query(int o, int l, int r, int ll, int rr) { if (ll <= l && rr >= r) return node[o]; int mid = (l + r) >> 1; push_down(o, l, r); if (rr <= mid) return query(o * 2, l, mid, ll, rr); if (ll > mid) return query(o * 2 + 1, mid + 1, r, ll, rr); Node lc = query(o * 2, l, mid, ll, rr); Node rc = query(o * 2 + 1, mid + 1, r, ll, rr); return merge(lc, rc); } int main(int argc, char ** argv) { freopen("game.in", "r", stdin); freopen("game.out", "w", stdout); int n, m; scanf("%d %d", &n, &m); C[0][0] = 1; for (int i = 1; i <= n; i++) { C[i][0] = 1; for (int j = 1; j <= 10; j++) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD; } for (int i = 1; i <= n; i++) scanf("%d", &a[i]); build(1, 1, n); for (int i = 1; i <= m; i++) { int l, r, opt; scanf("%d%d%d",&opt, &l, &r); if (opt == 1) { int c; scanf("%d", &c); c = (c % MOD + MOD) % MOD; modify1(1, 1, n, l, r, c); } else if (opt == 2) { modify2(1, 1, n, l, r); } else { int k; scanf("%d", &k); Node o = query(1, 1, n, l, r); printf("%d\n", o.f[k] % MOD); } } return 0; }