A. Cakey McCakeFace

按题意模拟即可。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 0, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int n, m;
int a[2005], b[2005];
int main()
{
while(~scanf("%d%d",&n, &m))
{
for(int i = 1; i <= n; ++i)
{
scanf("%d", &a[i]);
}
for(int i = 1; i <= m; ++i)
{
scanf("%d", &b[i]);
}
map<int,int>mop;
int cnt = -1, val;
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= m; ++j)if(b[j] >= a[i])
{
++mop[b[j] - a[i]];
}
}
for(auto it : mop)
{
if(it.second > cnt)
{
cnt = it.second;
val = it.first;
}
}
printf("%d\n", val);
}
return 0;
} /*
【trick&&吐槽】 【题意】 【分析】 【时间复杂度&&优化】 */

  

B. Table

枚举下底边,求出每个位置向上延伸的最大长度,枚举每个位置作为右下角,那么单调栈中每一个子矩形都可以对长宽都不超过它的询问产生贡献,通过差分二维前缀和,那么$O(1)$单点修改即可。

为了避免枚举单调栈中每一项,可以在每一项退栈时计算有多少个右下角可以与它产生贡献,这是对差分后的二维前缀和的一段区间加,再次差分前缀和转化成单点修改即可。

时间复杂度$O(xy+n+d)$。

#include<cstdio>
const int N=2010;
int n,m,_a,_b,i,j,a[N][N],b[N][N],f[N],q[N],t;
inline void work(int x,int y,int z,int o){
/*for(int i=y;i<=z;i++){
b[i-y][o]--;
b[i+1-x][o]++;
}
return;*/
b[0][o]--;
b[z-y+1][o]++;
b[y+1-x][o]++;
b[z+1-x+1][o]--;
}
int main(){
scanf("%d%d%d%d",&n,&m,&_a,&_b);
while(_a--){
int xl,xr,yl,yr;
scanf("%d%d%d%d",&xl,&xr,&yl,&yr);
a[xr][yr]++;
a[xl][yr]--;
a[xr][yl]--;
a[xl][yl]++;
}
for(i=n;i;i--)for(j=m;j;j--)a[i][j]+=a[i+1][j]+a[i][j+1]-a[i+1][j+1];
for(i=1;i<=n;i++)for(j=1;j<=m;j++)a[i][j]=a[i][j]==0; /*puts("");
for(i=1;i<=n;i++){
for(j=1;j<=m;j++)printf("%d",a[i][j]);
puts("");
}*/ for(i=1;i<=n;i++){
for(j=1;j<=m;j++)if(a[i][j])f[j]++;else f[j]=0;
for(q[t=0]=0,j=1;j<=m;q[++t]=j++){
while(t&&f[j]<f[q[t]]){
work(q[t-1]+1,q[t],j-1,f[q[t]]);
t--;
}
}
for(j=1;j<=t;j++)work(q[j-1]+1,q[j],m,f[q[j]]);
}
for(j=1;j<=n;j++)for(i=1;i<=m+5;i++)b[i][j]+=b[i-1][j];
for(i=m;i;i--)for(j=n;j;j--)b[i][j]+=b[i+1][j]+b[i][j+1]-b[i+1][j+1];
while(_b--)scanf("%d%d",&i,&j),printf("%d\n",b[j][i]);
}
/*
7 5 3 9
1 2 0 1
5 7 2 5
0 1 2 4
7 1
3 5
5 3
2 2
3 3
4 4
4 5
6 2
1 1
*/

  

C. Macarons

设$f[i][S]$表示考虑前$i$行,第$i$行每个位置是否被填充的情况为$S$的合法方案数。

逐格转移预处理出转移矩阵后快速幂即可。

时间复杂度$O(2^{3n}\log m)$。

#include<cstdio>
#define rep(i) for(int i=0;i<m;i++)
typedef long long ll;
const int N=260,P=1000000000;
int n,m,S,i,j,k,x,y,z,f[N],g[N];
ll K;
int A[N][N],B[N][N],C[N][N];
inline void up(int&a,int b){a=a+b<P?a+b:a+b-P;}
inline void mul(int A[][N],int B[][N],int F[][N]){
rep(i)rep(j)C[i][j]=0;
rep(i)rep(j)if(A[i][j])rep(k)if(B[j][k])C[i][k]=(1LL*A[i][j]*B[j][k]+C[i][k])%P;
rep(i)rep(j)F[i][j]=C[i][j];
}
int main(){
scanf("%d%lld",&n,&K);
m=1<<n;
for(S=0;S<m;S++){
for(j=0;j<m;j++)f[j]=g[j]=0;
f[S]=1;
for(i=0;i<n;i++){
for(j=0;j<m;j++)g[j]=0;
for(j=0;j<m;j++)if(f[j]){
if(!(j>>i&1)){
up(g[j^(1<<i)],f[j]);
}else{
up(g[j^(1<<i)],f[j]);
up(g[j],f[j]);
if(i&&!(j>>(i-1)&1))up(g[j|(1<<(i-1))],f[j]);
}
}
for(j=0;j<m;j++)f[j]=g[j];
}
for(j=0;j<m;j++)A[j][S]=f[j];
}
for(i=0;i<m;i++)B[i][i]=1;
for(;K;K>>=1,mul(A,A,A))if(K&1)mul(A,B,B);
printf("%d",B[m-1][m-1]);
}

  

D. Candy Chain

设$f[i][j]$表示将区间$[i,j]$全部消完的最大收益,$dp[i]$表示考虑前$i$个位置的最大收益,那么$dp[i]=\max(dp[i-1],dp[j-1]+f[j][i](1\leq j\leq i))$。

对于$f$的计算,设$g[i][j][k]$表示考虑区间$[i,j]$,最后一次要删去的串在字典树上位于$k$点的最大收益,要么枚举一个区间消掉,要么在字典树上往下走,要么消去$k$代表的字符串。

时间复杂度$O(n^4c)$,但常数很小,且无用状态很多,远远达不到上界。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=55,M=20005;
int n,m,i,j,k,x,tot,son[M][26],w[M],f[N][N],dp[N];
int g[N][M];
char a[N],b[N];
inline void up(int&a,int b){a<b?(a=b):0;}
inline void ins(int l,int v){
int x=0;
for(int i=0;i<l;i++){
int o=b[i]-'a';
if(!son[x][o])son[x][o]=++tot;
x=son[x][o];
}
up(w[x],v);
}
int main(){
for(i=1;i<M;i++)w[i]=-1;
scanf("%s",a+1);
n=strlen(a+1);
for(i=1;i<=n;i++)a[i]-='a';
scanf("%d",&m);
while(m--){
int l,w;
scanf("%s%d",b,&w);
l=strlen(b);
ins(l,w);
reverse(b,b+l);
ins(l,w);
}
for(i=0;i<=n+1;i++)for(j=0;j<=n+1;j++)f[i][j]=-1; for(i=n;i;i--){
for(j=i-1;j<=n+1;j++)for(k=0;k<=tot;k++)g[j][k]=-1;
g[i-1][0]=0;
for(j=i-1;j<=n;j++)for(k=0;k<=tot;k++)if(~g[j][k]){
for(x=j+1;x<=n;x++)if(~f[j+1][x])up(g[x][k],g[j][k]+f[j+1][x]);
if(j<n){
int y=son[k][a[j+1]];
if(y){
up(g[j+1][y],g[j][k]);
if(~w[y])up(g[j+1][0],g[j][k]+w[y]);
}
}
if(k==0)up(f[i][j],g[j][k]);
}
} for(i=1;i<=n;i++){
dp[i]=dp[i-1];
for(j=1;j<=i;j++)if(~f[j][i])up(dp[i],dp[j-1]+f[j][i]);
}
printf("%d",dp[n]);
}

  

E. Ingredients

拓扑排序之后背包即可。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 1e6 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int B, n;
char s1[N][24];
char s2[N][24];
char s3[N][24];
int c[N];
int v[N];
int cc[N];
int vv[N];
int ind[N];
int sta[N];
map<string, int>mop;
int ID;
vector< pair<int,int> >a[N];
int getid(char s[24])
{
if(!mop.count(s))
{
mop[s] = ++ID;
a[ID].clear();
cc[ID] = inf;
vv[ID] = -inf;
ind[ID] = 0;
}
return mop[s];
}
bool e[N];
LL f[10005];
int main()
{
while(~scanf("%d%d", &B, &n))
{
ID = 0;
mop.clear();
for(int i = 1; i <= n; ++i)
{
scanf("%s%s%s%d%d", s1[i], s2[i], s3[i], &c[i], &v[i]);
int z = getid(s1[i]);
int x = getid(s2[i]);
int y = getid(s3[i]);
++ind[z];
a[x].push_back({y, i});
a[y].push_back({x, i});
e[i] = 0;
}
int top = 0;
for(int i = 1; i <= ID; ++i)if(ind[i] == 0)
{
sta[++top] = i;
cc[i] = vv[i] = 0;
}
while(top)
{
int x = sta[top--];
for(auto it : a[x])
{
int y = it.first;
int o = it.second;
if(!e[o] && ind[y] == 0)
{
e[o] = 1;
int z = mop[s1[o]];
int cost = cc[x] + cc[y] + c[o];
int val = vv[x] + vv[y] + v[o];
if(cost < cc[z] || cost == cc[z] && val > vv[z])
{
cc[z] = cost;
vv[z] = val;
}
if(--ind[z] == 0)
{
sta[++top] = z;
}
}
}
}
MS(f, -63); f[0] = 0;
for(int i = 1; i <= ID; ++i)
{
//
//printf("cc = %d, vv = %d\n", cc[i], vv[i]);
//
for(int j = B; j >= cc[i]; --j)
{
gmax(f[j], f[j - cc[i]] + vv[i]);
}
}
int cost = 0;
LL val = 0;
for(int i = 1; i <= B; ++i)
{
if(f[i] > val)
{
val = f[i];
cost = i;
}
}
printf("%lld\n%d\n", val, cost);
}
return 0;
} /*
【trick&&吐槽】
6 2
pizza_tomato pizza_base tomato 1 2
pizza_classic pizza_tomato cheese 5 5 7 2
pizza_tomato pizza_base tomato 1 2
pizza_classic pizza_tomato cheese 5 5 9 2
pizza_tomato pizza_base tomato 1 2
pizza_classic pizza_tomato cheese 5 5 100 2
pizza_tomato pizza_base tomato 1 2
pizza_classic pizza_tomato cheese 5 5 【题意】 【分析】 【时间复杂度&&优化】 */

  

F. Shattered Cake

$ans=\frac{\sum_{i=1}^n w_il_i}{W}$。

#include<cstdio>
int w,n;long long s;
int main(){
scanf("%d%d",&w,&n);
while(n--){
int x,y;
scanf("%d%d",&x,&y);
s+=x*y;
}
printf("%lld",s/w);
}

  

G. Cordon Bleu

考虑费用流建图,新建一个容量为$n-1$的虚点,表示从餐厅出发的快递员,剩下部分显然,然后求最小费用最大流。

这样边数为$O(n^2)$,不能接受。注意到这些边费用都是曼哈顿距离,将绝对值拆开后$4$个象限分别用可持久化线段树优化建图即可。

如此一来点数边数均为$O(n\log n)$,可以通过。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 70000, M = 1e6 + 10, Z = 1e9 + 7, inf = 1e9;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei; int id, ST, ED;
int first[N];
int w[M], c[M], cap[M], cost[M], nxt[M];
int f[N];
int pe[N];
bool e[N];
int tot; int FLAG=0; void ins(int x, int y, int cap_, int cost_)
{
if(!x||!y)return;
if(FLAG)swap(x,y);
id ++;
w[id] = y;
cap[id] = cap_;
cost[id] = cost_;
nxt[id] = first[x];
first[x] = id; id ++;
w[id] = x;
cap[id] = 0;
cost[id] = -cost_;
nxt[id] = first[y];
first[y] = id;
}
int q[N];
unsigned short head,tail; void inq(int x, int cost_)
{
if(cost_ >= f[x]) return;
f[x] = cost_;
//pe[x] = pe_;
if(e[x]) return; e[x] = 1;
// if(cost_<q[head])q[--head]=x;else
q[++tail]=x;
} int vis[N], tim;
int dfs(int x, int all)
{
if(x == ST) return all;
int use = 0;
vis[x] = tim;
for(int z = first[x]; z; z = nxt[z]) if(cap[z ^ 1]){
int y = w[z];
if(vis[y] != tim && f[y] + cost[z ^ 1] == f[x]){
int tmp = dfs(y, min(cap[z ^ 1], all - use));
cap[z ^ 1] -= tmp;
cap[z] += tmp;
use += tmp;
if(use == all) break;
}
}
return use;
}
bool spfa()
{
for(int i=0;i<=tot+10;i++)f[i]=inf;
cap[0] = inf;
head=1,tail=0;
inq(ST, 0);
while(head!=tail+1){
int x = q[head++]; e[x]=0;
for(int z = first[x]; z; z = nxt[z]){
if(cap[z]) inq(w[z], f[x] + cost[z]);
}
}
return f[ED] < inf;
} int MCMF()
{
int maxflow = 0;
int mincost = 0;
while(spfa()){
int flow;
while(++tim, flow = dfs(ED, inf))
{
maxflow += flow;
mincost += f[ED] * flow;
}
}
//printf("%d\n",maxflow);
return mincost;
} /*int MCMF()
{
int maxflow = 0;
int mincost = 0;
while(spfa()){
int flow = ~0U>>1;
int x = ED;
while(x != ST){
gmin(flow, cap[pe[x]]);
x = w[pe[x] ^ 1];
}
maxflow += flow;
mincost += f[ED] * flow;
x = ED;
while(x != ST){
cap[pe[x]] -= flow;
cap[pe[x] ^ 1] += flow;
x = w[pe[x] ^ 1];
}
}
return mincost;
//printf("%d %d\n", maxflow, mincost);
}*/ struct point
{
int x, y;
};
int dis(point a, point b)
{
return abs(a.x - b.x) + abs(a.y - b.y);
}
int n, m;
point a, b[N], cc[N];
int ans;
int pool[N];
inline bool cmpx(int x,int y){
return b[x].x<b[y].x;
}
int root0[1111],root1[1111];
int sonl[200000],sonr[200000];
int Ins(int x,int a,int b,int c,int p,int w){
int y=++tot;
if(a==b){
ins(y,x,inf,0);
ins(y,p,inf,w);
return y;
}
int mid=(a+b)>>1;
if(c<=mid){
sonl[y]=Ins(sonl[x],a,mid,c,p,w);
sonr[y]=sonr[x];
}else{
sonl[y]=sonl[x];
sonr[y]=Ins(sonr[x],mid+1,b,c,p,w);
}
ins(y,sonl[y],inf,0);
ins(y,sonr[y],inf,0);
return y;
}
void ask(int x,int a,int b,int c,int d,int p,int w){
if(!x)return;
if(c<=a&&b<=d){
ins(p,x,inf,w);
return;
}
int mid=(a+b)>>1;
if(c<=mid)ask(sonl[x],a,mid,c,d,p,w);
if(d>mid)ask(sonr[x],mid+1,b,c,d,p,w);
}
void solve()
{
MS(first, 0); id = 1;
ED = m + n + 1;
ST = m + n + 4;
int R = m + n + 2;
for(int i = 1; i <= m; i ++)
{
ins(ST, i, 1, 0);
/*for(int j = 1; j <= n; j ++)
{
ins(i, j + m, 1, dis(cc[i], b[j]));
}*/
} tot=ST; for(int i=1;i<=n;i++)pool[i]=i;
sort(pool+1,pool+n+1,cmpx); root0[0]=root1[0]=0;
for(int i=1;i<=n;i++){
int x=pool[i];
root0[i]=Ins(root0[i-1],0,2000,b[x].y,x+m,-b[x].x-b[x].y);
root1[i]=Ins(root1[i-1],0,2000,b[x].y,x+m,-b[x].x+b[x].y);
}
for(int i=1;i<=m;i++){
int j=0;
int X=cc[i].x,Y=cc[i].y;
while(j<n&&b[pool[j+1]].x<=X)j++;
ask(root0[j],0,2000,0,Y,i,X+Y);
ask(root1[j],0,2000,Y,2000,i,X-Y);
} reverse(pool+1,pool+n+1);
for(int i=1;i<=n;i++){
int x=pool[i];
root0[i]=Ins(root0[i-1],0,2000,b[x].y,x+m,b[x].x-b[x].y);
root1[i]=Ins(root1[i-1],0,2000,b[x].y,x+m,b[x].x+b[x].y);
}
for(int i=1;i<=m;i++){
int j=0;
int X=cc[i].x,Y=cc[i].y;
while(j<n&&b[pool[j+1]].x>=X)j++;
ask(root0[j],0,2000,0,Y,i,-X+Y);
ask(root1[j],0,2000,Y,2000,i,-X-Y);
} for(int i = 1; i <= n; i ++)
{
ins(R, m + i, 1, dis(a, b[i]));
ins(m + i, ED, 1, 0);
}
ins(ST, R, n - 1 , 0);
//printf("%d %d\n",tot,id);return;
if(FLAG)swap(ST,ED); ans += MCMF();
printf("%d\n", ans);
}
inline void getnum(int &x){
scanf("%d",&x);
//x=rand()%2001-1000;
x+=1000;
}
int main()
{
scanf("%d%d", &n, &m);//huowu ren
for(int i = 1; i <= n; i ++){
getnum(b[i].x);
getnum(b[i].y);
}
for(int i = 1; i <= m; i ++){
getnum(cc[i].x);
getnum(cc[i].y);
}
getnum(a.x);
getnum(a.y); ans = 0;
for(int i = 1; i <= n; ++i)
{
ans += dis(a, b[i]);
} solve();
return 0;
} /*
【trick&&吐槽】
3 10
0 0
10 0
0 10 【题意】 【分析】 【时间复杂度&&优化】 */

  

H. Kabobs

留坑。

I. Burglary

设$f[i][j][k]$表示考虑从上往下前$i$行,目前两条路线分别位于第$i$行的第$j$和第$k$根管道上的最大收益,暴力转移即可。

时间复杂度$O(10^4n)$。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 1005, M = 5005, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int n, m;
char s[M];
int gv[N];
int v[N][M];
int p[N][M];
int gt[N];
int t[N][M];
int sum[N][M];
int f[N][12][12];
int main()
{
while (~scanf("%d%d", &n, &m))
{
for (int i = 1; i <= n; ++i)
{
scanf("%s", s + 1);
gv[i] = 0;
p[i][0] = 0;
v[i][0] = 0;
for (int j = 1; j <= m; ++j)if (isdigit(s[j]))
{
v[i][++gv[i]] = s[j] - '0';
p[i][gv[i]] = j;
}
++gv[i];
p[i][gv[i]] = m + 1;
v[i][gv[i]] = 0;
for (int j = 1; j <= gv[i]; ++j)
{
sum[i][j] = sum[i][j - 1] + v[i][j];
}
//
scanf("%s", s + 1);
gt[i] = 0;
for (int j = 1; j <= m; ++j)if (s[j] == '|')
{
t[i][++gt[i]] = j;
}
}
MS(f, -63);
MS(f[1], 0);
for (int o = 1; o < n; ++o)
{
for (int i = 1; i <= gt[o]; ++i)
{
for (int j = i; j <= gt[o]; ++j)if (f[o][i][j] >= 0)
{
for (int ii = 1; ii <= gt[o + 1]; ++ii)
{
for (int jj = ii; jj <= gt[o + 1]; ++jj)
{
int l1 = min(t[o][i], t[o + 1][ii]);
int r1 = max(t[o][i], t[o + 1][ii]); int l2 = min(t[o][j], t[o + 1][jj]);
int r2 = max(t[o][j], t[o + 1][jj]); int ll1 = lower_bound(p[o + 1], p[o + 1] + gv[o + 1] + 1, l1) - p[o + 1];
int rr1 = upper_bound(p[o + 1], p[o + 1] + gv[o + 1] + 1, r1) - p[o + 1] - 1; int ll2 = lower_bound(p[o + 1], p[o + 1] + gv[o + 1] + 1, l2) - p[o + 1];
int rr2 = upper_bound(p[o + 1], p[o + 1] + gv[o + 1] + 1, r2) - p[o + 1] - 1; //
int ll = max(ll1, ll2);
int rr = min(rr1, rr2);
if (ll <= rr)
{
int inside = sum[o + 1][rr]; if (ll)inside -= sum[o + 1][ll - 1];
if (inside)continue;
} l1 = upper_bound(p[o + 1], p[o + 1] + gv[o + 1] + 1, l1) - p[o + 1] - 1;
r1 = lower_bound(p[o + 1], p[o + 1] + gv[o + 1] + 1, r1) - p[o + 1]; l2 = upper_bound(p[o + 1], p[o + 1] + gv[o + 1] + 1, l2) - p[o + 1] - 1;
r2 = lower_bound(p[o + 1], p[o + 1] + gv[o + 1] + 1, r2) - p[o + 1]; //
if (l1 > l2)
{
swap(l1, l2);
swap(r1, r2);
}
//one segment
int val;
if (l2 <= r1 + 1)
{
int l = l1;
int r = max(r1, r2);
val = sum[o + 1][r]; if (l)val -= sum[o + 1][l - 1]; }
//two segment
else
{
val = sum[o + 1][r1]; if (l1)val -= sum[o + 1][l1 - 1];
val += sum[o + 1][r2]; if (l2)val -= sum[o + 1][l2 - 1];
}
gmax(f[o + 1][ii][jj], f[o][i][j] + val);
}
}
}
}
} int ans = 0;
for (int o = 1; o <= n; ++o)
{
for (int i = 1; i <= gt[o]; ++i)
{
for (int j = i; j <= gt[o]; ++j)if (f[o][i][j] >= 0)
{
int l = t[o][i];
int r = t[o][j];
l = upper_bound(p[o + 1], p[o + 1] + gv[o + 1] + 1, l) - p[o + 1] - 1;
r = lower_bound(p[o + 1], p[o + 1] + gv[o + 1] + 1, r) - p[o + 1];
int val = sum[o + 1][r]; if (l)val -= sum[o + 1][l - 1];
gmax(ans, f[o][i][j] + val);
}
}
}
printf("%d\n", ans);
}
return 0;
} /*
【trick&&吐槽】 【题意】 【分析】 【时间复杂度&&优化】
5 20
--------------------
.|.....|...|......|.
1-1--1115-3-1-1--1-1
....|.........|.....
---1-11-1-11---1--3-
.......|.........|..
-7----9-4-----------
..|.................
--------9-----------
.|.................| */

  

J. Frosting on the Cake

按题意模拟即可。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 0, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
int n;
LL a[3], b[3], c[3];
int main()
{
while(~scanf("%d",&n))
{
MS(a, 0); MS(b, 0); MS(c, 0);
for(int i = 1; i <= n; ++i)
{
int x; scanf("%d", &x);
a[i % 3] += x;
}
for(int i = 1; i <= n; ++i)
{
int x; scanf("%d", &x);
b[i % 3] += x;
}
for(int i = 0; i < 3; ++i)
{
for(int j = 0; j < 3; ++j)
{
c[(i + j) % 3] += a[i] * b[j];
}
}
printf("%lld %lld %lld\n", c[0], c[1], c[2]);
}
return 0;
} /*
【trick&&吐槽】 【题意】 【分析】 【时间复杂度&&优化】 */

  

K. Blowing Candles

求凸包后旋转卡壳,注意特判所有点共线的情况。

#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { }
#define MS(x, y) memset(x, y, sizeof(x))
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b > a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b < a)a = b; }
const int N = 2e5 + 10, M = 0, Z = 1e9 + 7, inf = 0x3f3f3f3f;
template <class T1, class T2>inline void gadd(T1 &a, T2 b) { a = (a + b) % Z; }
int casenum, casei;
LL sqr(LL x)
{
return x * x;
}
struct point
{
LL x, y;
point(){}
point(LL x, LL y) : x(x), y(y) {}
friend point operator + (const point &a, const point &b){
return point(a.x + b.x, a.y + b.y);
}
friend point operator - (const point &a, const point &b){
return point(a.x - b.x, a.y - b.y);
}
friend point operator * (const point &a, const double &b){
return point(a.x * b, a.y * b);
}
friend point operator / (const point &a, const double &b){
return point(a.x / b, a.y / b);
}
friend bool operator == (const point &a, const point &b){
return a.x == b.x && a.y == b.y;
}
};
LL det(point a, point b)
{
return a.x * b.y - a.y * b.x;
}
LL dot(point a, point b)
{
return a.x * b.x + a.y * b.y;
}
LL dist(point a, point b)
{
return sqr(a.x - b.x) + sqr(a.y - b.y);
}
struct polygon_convex
{
vector<point> p;
polygon_convex(int size = 0){
p.resize(size);
}
};
bool comp_less(const point &a, const point &b)
{
return a.x - b.x < 0 || a.x - b.x == 0 && a.y - b.y < 0;
}
polygon_convex convex_hull(vector<point> a)
{
polygon_convex res(2 * a.size() + 5);
sort(a.begin(), a.end(), comp_less);
a.erase(unique(a.begin(), a.end()), a.end());
int m = 0;
for(int i = 0; i < a.size(); i ++){
while(m > 1 && det(res.p[m - 1] - res.p[m - 2], a[i] - res.p[m - 2]) <= 0) -- m;
res.p[m ++] = a[i];
}
int k = m;
for(int i = int(a.size()) - 2; i >= 0; i --){
while(m > k && det(res.p[m - 1] - res.p[m - 2], a[i] - res.p[m - 2]) <= 0) -- m;
res.p[m ++] = a[i];
}
res.p.resize(m);
if(a.size() > 1) res.p.resize(m - 1);
return res;
} LL cross(point a, point b, point c)
{
return (c.x - a.x) * (b.y - a.y) - (b.x - a.x) * (c.y - a.y);
}
int R; double rotating_calipers(point *p, int n)
{
int U = 1;
double ans = 2.0 * R;
p[n] = p[0];
for(int i = 0; i < n; i ++){
while(cross(p[i], p[i + 1], p[U + 1]) - cross(p[i], p[i + 1], p[U]) <= 0) U = (U + 1) % n;
double d = sqrt(dist(p[i], p[i + 1]));
double h = 1.0 * fabs(cross(p[i], p[i + 1], p[U])) / d;
gmin(ans, h);
}
return ans;
}
int n;
point t, p[N];
polygon_convex a;
int main()
{
scanf("%d%d", &n, &R);
for(int i = 0; i < n; i ++){
scanf("%lld%lld", &t.x, &t.y);
a.p.push_back(t);
}
a = convex_hull(a.p);
n = a.p.size();
for(int i = 0; i < n; i ++){
p[i] = a.p[i];
}
double ans;
if(n <= 2){
printf("0.000000000");
}
else {
ans = rotating_calipers(p, n);
printf("%.10f\n", ans);
}
return 0;
} /*
【trick&&吐槽】
3 10
0 0
10 0
0 10 【题意】 【分析】 【时间复杂度&&优化】 */

  

2017-2018 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2017)的更多相关文章

  1. Gym 2009-2010 ACM ICPC Southwestern European Regional Programming Contest (SWERC 2009) A. Trick or Treat (三分)

    题意:在二维坐标轴上给你一堆点,在x轴上找一个点,使得该点到其他点的最大距离最小. 题解:随便找几个点画个图,不难发现,答案具有凹凸性,有极小值,所以我们直接三分来找即可. 代码: int n; lo ...

  2. 2016-2017 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2016)

    A. Within Arm's Reach 留坑. B. Bribing Eve 枚举经过$1$号点的所有直线,统计直线右侧的点数,旋转卡壳即可. 时间复杂度$O(n\log n)$. #includ ...

  3. 2016-2017 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2016) F dfs序+树状数组

    Performance ReviewEmployee performance reviews are a necessary evil in any company. In a performance ...

  4. 2016-2017 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2016) B - Bribing Eve

    地址:http://codeforces.com/gym/101174/attachments 题目:pdf,略 思路: 把每个人的(x1,x2)抽象成点(xi,yi). 当1号比i号排名高时有==& ...

  5. 2016-2017 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2016) D.Dinner Bet 概率DP+排列组合

    题目链接:点这里 题意: 1~N标号的球 现在A有C个,B有C个 每次可以随机得到D个不同的球(1~N);问你A或B中的C个球都出现一次的 期望次数 题解: dp[i][j][k]表示 随机出现了i个 ...

  6. 2016-2017 ACM-ICPC Southwestern European Regional Programming Contest (SWERC 2016) E.Passwords AC自动机+dp

    题目链接:点这里 题意: 让你构造一个长度范围在[A,B]之间 字符串(大小写字母,数字),问你有多少种方案 需要满足条件一下: 1:构成串中至少包含一个数字,一个大写字母,一个小写字母:   2:不 ...

  7. 2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017)

    2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017) 全靠 wxh的博客 补完这套.wx ...

  8. 2017-2018 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2017) Solution

    A:Concerts 题意:给出一个串T, 一个串S,求串S中有多少个串T,可以重复,但是两个字符间的距离要满足给出的数据要求 思路:先顺序统计第一个T中的字符在S中有多少个,然后对于第二位的以及后面 ...

  9. 2018-2019 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2018)

    layout: post title: 2018-2019 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 201 ...

随机推荐

  1. gcc __thread关键字

    https://blog.csdn.net/xj178926426/article/details/54345449 EventLoop.cpp __thread EventLoop* t_loopI ...

  2. Stanford Local 2016 G "Ground Defense"(线段树)

    传送门 题意: 有 n 个城市,编号 1~n: 有两种操作:Update,Query Update: E i s a d 更新区间[ i,i+d-1 ], i 节点降落 s 人, i+1 节点降落 s ...

  3. Pandas系列(二)- DataFrame数据框

    一.初识DataFrame dataFrame 是一个带有索引的二维数据结构,每列可以有自己的名字,并且可以有不同的数据类型.你可以把它想象成一个 excel 表格或者数据库中的一张表DataFram ...

  4. Shiro与CAS整合实现单点登录

    1.简介 CAS:Yale 大学发起的一个开源项目,旨在为 Web 应用系统提供一种可靠的单点登录方法. Shiro:Apache Shiro是一个Java安全框架,可以帮助我们完成认证.授权.会话管 ...

  5. ACM-ICPC 2018 徐州赛区网络预赛 H Ryuji doesn't want to study (树状数组差分)

    https://nanti.jisuanke.com/t/31460 题意 两个操作.1:查询区间[l,r]的和,设长度为L=r-l+1, sum=a[l]*L+a[l+1]*(L-1)+...+a[ ...

  6. Django 数据库查询集合(双下划线连表操作)

    Django是一款优秀的web框架,有着自己的ORM数据库模型.在项目中一直使用django数据库,写一篇文章专门记录一下数据库操作.略写django工程创建过程,详写查询过程.可以和sqlalche ...

  7. [物理学与PDEs]第2章习题10 一维理想流体力学方程组的 Lagrange 形式

    试证明: 一维理想流体力学方程组的 Lagrange 形式 (5. 22)-(5. 24) 也可写成如下形式 $$\beex \bea \cfrac{\p \tau}{\p t}-\cfrac{\p ...

  8. [物理学与PDEs]第1章习题2 均匀带电球面的电场强度与电势

    设有一均匀分布着电荷的半径为 $R$ 的球面, 其电荷密度 (即单位面积上的电荷量) 为 $\sigma$. 试求该球面所形成电场的电场强度及电势. 解答: 设 $P$ 距圆心的距离为 $r$, 不妨 ...

  9. java8 按条件过滤集合

    //黄色部分为过滤条件list.stream().filter(user-> user.getId() > 5 && "1组".equals(user. ...

  10. 个人认为一个比较完整,基于tp5平台,可快速开发的B2C平台

    现在全民创业,做电商的人很多,大大小小的技术公司也很多,报价也很奇葩,从100到十万的都有,把人都能转晕,有朋友问我,你们创业是不是很赚钱,其实,外行不知道内行的苦,创业控制成本第一,活下来才能赚钱. ...