T1
把修改放到差分序列上做,这样每次修改只需要修改两个位置,且每次修改会对后面的所有温度产生影响
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
const int N=10000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define fir first
#define sec second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define maxd 998244353
#define eps 1e-8
int n,m,a[200200];
ll f[200100];
ll s,t,ans;
int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
void modify(int pos,ll val)
{
if (pos>n) return;
if (f[pos]>0) ans+=s*f[pos];
else ans+=t*f[pos];
f[pos]+=val;
if (f[pos]>0) ans-=s*f[pos];
else ans-=t*f[pos];
}
signed main()
{
n=read();m=read();s=read();t=read();
rep(i,0,n) a[i]=read();
rep(i,1,n) f[i]=a[i]-a[i-1];
ans=0;
rep(i,1,n)
if (f[i]>0) ans-=s*f[i];
else ans-=t*f[i];
while (m--)
{
int l=read(),r=read(),x=read();
modify(l,x);modify(r+1,-x);
printf("%lld\n",ans);
}
return 0;
}
T2
不难发现如果按照“快车->准快车->慢车”的顺序坐车一定不会更劣
对于每一段快车区间\((s_i,s_{i+1}]\),考虑如何求出最大的可到达车站
我们在\(s_i\)下车后会有一段剩余时间,记作\(rst_i\),和最开始的结论同理,我们希望在“最后一个可以使用慢车到达的车站”处建立一个准快车车站,使得从\(s_i\)可以直接到达那里,证明的话考虑往前或往后调整都不会是更优的
这样的话我们就有\(O(mk)\)个可以考虑的准快车建立点,使用优先队列贪心即可
注意一些奇奇怪怪的特判
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
const int N=10000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define fir first
#define sec second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define maxd 998244353
#define int long long
#define eps 1e-8
int n,m,k,now[5050],s[5050];
ll a,b,c,tot,rst[5050];
priority_queue<int> q;
int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
signed main()
{
n=read();m=read();k=read();
scanf("%lld%lld%lld%lld",&a,&b,&c,&tot);
rep(i,1,m)
{
s[i]=read();
rst[i]=tot-b*(s[i]-1);
now[i]=s[i];
}
int ans=0;
//rep(i,1,m) cout << now[i] << " ";cout << endl;
if (b*(s[m]-1)>tot) ans--;
rep(i,1,m-1)
{
if (rst[i]<0) continue;
int nxt=min(s[i+1],s[i]+rst[i]/a+1);
ans+=(nxt-s[i]);
rst[i]-=c*(nxt-s[i]);
now[i]=nxt;
}
rep(i,1,k)
{
rep(j,1,m-1)
{
if (rst[j]<0) continue;
int nxt=min(s[j+1],now[j]+rst[j]/a+1);
q.push(nxt-now[j]);
rst[j]-=c*(nxt-now[j]);
now[j]=nxt;
}
}
rep(i,1,k-m)
{
if (q.empty()) break;
ans+=q.top();q.pop();
}
printf("%lld",ans);
return 0;
}
T3
画一下的话可以发现合法方案就是在四个角上的阶梯形,由于四种情况等价我们可以将矩阵旋转后只处理左下角的阶梯形,最后取个\(min\)即可
题目中由很明显的二分答案的暗示,但是看起来\(check\)不太容易
考虑矩阵的全局\(max\)和\(min\)值,对于我们二分出来的\(mid\),我们考虑左下角的阶梯有\(\geq mid+min\),右上角的有\(\leq max-mid\),由于\(max\)和\(min\)不会在同一个阶梯里,所以这样做我们一定能考虑到最优解,之后维护一个当前行的右端点指针(单调不降),每行判断一下在左下角不合法的点是否在右上角即可
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<set>
#include<map>
using namespace std;
typedef long long ll;
typedef long double db;
typedef pair<int,int> pii;
const int N=10000;
const db pi=acos(-1.0);
#define lowbit(x) (x)&(-x)
#define sqr(x) (x)*(x)
#define rep(i,a,b) for (register int i=a;i<=b;i++)
#define per(i,a,b) for (register int i=a;i>=b;i--)
#define fir first
#define sec second
#define mp(a,b) make_pair(a,b)
#define pb(a) push_back(a)
#define maxd 2e9
#define eps 1e-8
int n,m,a[2020][2020],ans=maxd,mx=0,mn=maxd;
int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
void reverse1()
{
rep(i,1,n/2) rep(j,1,m) swap(a[i][j],a[n-i+1][j]);
}
void reverse2()
{
rep(i,1,n) rep(j,1,m/2) swap(a[i][j],a[i][m-j+1]);
}
bool chk(int mid)
{
int now=0;
rep(i,1,n)
{
rep(j,1,m)
if (a[i][j]<mx-mid) now=max(now,j);
rep(j,1,m)
if ((a[i][j]>mid+mn) && (j<=now)) return 0;
}
return 1;
}
void solve()
{
int l=0,r=mx-mn,now=0;
while (l<=r)
{
int mid=(l+r)>>1;
if (chk(mid)) {now=mid;r=mid-1;}
else l=mid+1;
}
ans=min(ans,now);
}
int main()
{
n=read();m=read();
rep(i,1,n) rep(j,1,m)
{
a[i][j]=read();
mx=max(a[i][j],mx);
mn=min(a[i][j],mn);
}
solve();
reverse1();
solve();
reverse2();
solve();
reverse1();
solve();
printf("%d",ans);
return 0;
}
T4
待填坑