标签:online mil tps for lock mes 个人 art 最小化
#include<bits/stdc++.h>
#define pii pair<int,int>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 1e2+10;
int n,a[N],mx[N][N],mn[N][N],ans;
int st,lim = 1000;
void init(){
memset(mx,-0x3f,sizeof mx);
memset(mn,0x3f,sizeof mn);
for(int i=1;i<=n+1;++i) mx[i][i-1] = mn[i][i-1] = 0;
for(int l=n;l>0;--l){
for(int r=l;r<=n;++r){
int ll = l,rr = r,son;
if(a[ll]>=a[rr]) son = a[ll++]; // 儿子取走左边的
else son = a[rr--]; // 取走右边的
mx[l][r] = max(mx[l][r],mx[ll][rr-1]+a[rr]-son); // 取左边
mx[l][r] = max(mx[l][r],mx[ll+1][rr]+a[ll]-son); // 取右边
mn[l][r] = min(mn[l][r],mn[ll][rr-1]+a[rr]-son);
mn[l][r] = min(mn[l][r],mn[ll+1][rr]+a[ll]-son);
}
}
}
void dfs(int l,int r,int dif){
if(l>r){ // 搜索到终点
if(dif<0) ans = max(ans,dif); // dif为当前爸爸比儿子少的
return ;
}
if(mn[l][r]+dif>=0 || mx[l][r]+dif<=ans) return ; // 可行性剪枝与最优化剪枝
if(mx[l][r]+dif<0){
ans = max(ans,mx[l][r]+dif);
return ;
}
if(clock()-st>lim) return ; // 超时停止搜索
int son;
if(a[l]>=a[r]) son = a[l++]; // 儿子优先拿大的
else son = a[r--];
dfs(l+1,r,dif+a[l]-son); // 取左边
dfs(l,r-1,dif+a[r]-son); // 取右边
}
int main(){
while(scanf("%d",&n)==1){
memset(a,0,sizeof a);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
}
init();
st = clock();
ans = -inf; // 爸爸比儿子少拿的 最后要取反
dfs(1,n,0);
if(ans == -inf) puts("The child will be unhappy...");
else printf("%d\n",-ans);
}
return 0;
}
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
using namespace std;
const int inf = 0x3f3f3f3f;
const int MOD = 998244353;
struct mat{
ll a[2][2];
mat operator *(mat b){
mat res; res.a[0][0] = res.a[0][1] = res.a[1][0] = res.a[1][1] = 0;
for(int i=0;i<2;++i){
for(int k=0;k<2;++k){
for(int j=0;j<2;++j){
res.a[i][j] = (a[i][k] * b.a[k][j] %MOD + res.a[i][j])%MOD;
}
}
}
return res;
}
void init(){
a[0][0] = a[0][1] = a[1][0] = 1; a[1][1] = 0;
}
};
mat qpow(mat c,ll b){
mat res; res.a[0][0] = res.a[1][1] = 1; res.a[1][0] = res.a[0][1] = 0;
while(b){
if(b%2) res = res*c;
b>>=1;
c = c*c;
}
return res;
}
int main(){
ll k;
while(scanf("%lld",&k)!=EOF){
mat res; res.init();
res = qpow(res,k*2+3);
printf("%lld\n",(res.a[1][0]-1+MOD)%MOD);
}
return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define lson(p) (p<<1)
#define rson(p) (p<<1|1)
#define ll long long
const int N = 2e4+10;
int n,sum[N],v[N],f[N][202];
void gmax(int &a,int b){
if(b>a) a = b;
}
int main(){
int t; scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=n;i>=1;--i)// 反向dp,从后往前拿,所以输入要倒序
scanf("%d",&v[i]);
for(int i=1;i<=n;++i){
sum[i] = sum[i-1] + v[i];
}
int m = sqrt(n*2);
while((1+m)*m >n*2) --m;
for(int i=1;i<=n;++i){ // 还剩多少堆
int top = min(i,m);
for(int j=1;j<=top;++j){ // 当前这轮拿j堆
f[i][j] = sum[i] - sum[i-j] - f[i-j][j]; // 下次拿j堆
if(i>j) gmax(f[i][j],sum[i] - sum[i-j-1] - f[i-j-1][j+1]); // 下次拿j+1堆
}
}
printf("%d\n",f[n][1]); // 反向dp f[n][1] 为答案
}
return 0;
}
#include<bits/stdc++.h>
#define pii pair<int,int>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 1e5+10;
struct node{
int u,v,w,nxt;
}e[N*2];
int head[N],tot;
int dp[N][2],a[N],n; // 0 买 1 卖
void add(int u,int v,int w){
e[tot] = (node){u,v,w,head[u]}; head[u] = tot++;
e[tot] = (node){v,u,w,head[v]}; head[v] = tot++;
}
void init(){
tot = 0; memset(head,-1,sizeof head);
memset(dp,0,sizeof dp);
}
void dfs(int u,int fa){
for(int i=head[u];~i;i=e[i].nxt){
if(e[i].v == fa) continue;
dp[e[i].v][0] = max(-a[e[i].v],dp[u][0]-e[i].w); // 儿子买
dp[e[i].v][1] = a[e[i].v] + dp[u][0] - e[i].w; // 儿子卖给父亲
dfs(e[i].v,u);
dp[u][1] = max(dp[e[i].v][0]+a[u] -e[i].w,dp[u][1]);
dp[u][0] = max(dp[e[i].v][0]-e[i].w,dp[u][0]);
}
}
int main(){
int t; scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d",&a[i]);
init();
int u,v,w;
for(int i=1;i<n;++i){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
dp[1][0] = -a[1];
dfs(1,0);
int ans = 0;
for(int i=1;i<=n;++i){
ans = max(ans,dp[i][1]);
}
printf("%d\n",ans);
}
}
#include<bits/stdc++.h>
using namespace std;
#define lson(p) (p<<1)
#define rson(p) (p<<1|1)
#define ll long long
const int N = 5e5+10;
struct Edge{
int u,v,w,nxt;
}e[N*2];
int head[N],tot;
int top[N],fa[N],deep[N],num[N],L[N],R[N],son[N]; // 重儿子
int pos;
void addedge(int u,int v,int w=0){e[tot] = (Edge){u,v,w,head[u]}; head[u] = tot++;}
struct node{
int u,v,la;
bool operator <(node b){
return deep[la] > deep[b.la];
}
};
vector<node> ve;
//第一遍dfs 处理fa,num,deep,son
void dfs1(int u,int pre,int d){
deep[u] = d;
fa[u] = pre;
num[u] = 1;
for(int i=head[u];~i;i=e[i].nxt){
int v = e[i].v;
if(v!=pre){
dfs1(v,u,d+1);
num[u] += num[v];
if(son[u] == -1 || num[v] > num[son[u]])
son[u] = v;
}
}
}
// 第二遍dfs 处理 top,p,fp
void dfs2(int u,int sp){
top[u] = sp;
L[u] = ++pos;
if(son[u]== -1){
R[u] = pos ;
return ;
}
dfs2(son[u],sp); // 当前链继续走重儿子
for(int i=head[u];i!=-1;i=e[i].nxt){
int v = e[i].v;
if( v!= son[u] && v!=fa[u])
dfs2(v,v); // 以自己为链首的新链
}
R[u] = pos ;
}
int n,m;
struct BIT{
int a[N];
void init(){
memset(a,0,sizeof a);
}
int lowbit(int x){
return x&(-x);
}
void update(int x,int pos){
for(int i=pos;i<=n;i+=lowbit(i)) a[i] += x;
}
int query(int pos){
int res = 0;
for(int i=pos;i;i-=lowbit(i)) res += a[i];
return res;
}
}bt;
int lca(int x,int y){
while(top[x]!=top[y]){
if(deep[top[x]] > deep[top[y]]) x = fa[top[x]];
else y = fa[top[y]];
}
return deep[x] < deep[y] ? x:y;
}
void init(){
memset(head,-1,sizeof(head));memset(son,-1,sizeof(son));
bt.init();ve.clear();tot = 0;pos = 0;
}
int main(){
while(scanf("%d",&n)==1){
int u,v,ans=0;
init();
for(int i=1;i<=n;++i){
scanf("%d%d",&u,&v);
addedge(u,v);
addedge(v,u);
}
dfs1(0,0,0); // 题目默认0为根节点
dfs2(0,0);
scanf("%d",&m);
for(int i=1;i<=m;++i){
scanf("%d%d",&u,&v);
ve.push_back({u,v,lca(u,v)});
}
sort(ve.begin(),ve.end());
for(auto item:ve){
u = item.u, v = item.v;
if(bt.query(L[u]) || bt.query(L[v])) continue; // 已经被割掉的点覆盖
bt.update(1,L[item.la]) ; bt.update(-1,R[item.la]+1); // 割去他们的lca
ans++;
}
printf("%d\n",ans);
}
return 0;
}
#include<bits/stdc++.h>
#define pii pair<int,int>
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 1e6+10;
int a[N],dp[N];
int n;
int main(){
while(scanf("%d",&n)==1){
int val;
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
}
for(int i=1;i<=n;++i){
scanf("%d",&val); a[i]-=val;
}
int ans = 0,pos=0;
for(int i=1;i<=n;++i){
dp[i] = dp[i-1] + a[i];
if(dp[i]<ans){// 前缀和为负数是移不到最后的,要把最小的那个对应的堆数移到后面,则剩下的肯定全是正的
ans = dp[i];
pos = i;
}
}
printf("%d\n",pos);
}
}
2017 ACM/ICPC Asia Regional Shenyang Online 部分刷题记录
标签:online mil tps for lock mes 个人 art 最小化
原文地址:https://www.cnblogs.com/xxrlz/p/11688526.html