2017/8/7 离线赛
来源:互联网 发布:海文网络计划软件教程 编辑:程序博客网 时间:2024/05/22 04:56
T1 Codechef JAN17 务农政策
这题的解法很好想,就是每次询问时枚举每个矩形,然后求出最小的花费, 每个矩形的终态就是这个矩形中最高的那块,我们只要用二维前缀和维护每个矩形的权值和,再求出每个矩形中最大的权值即可。难点在怎么求每个矩形的最大权值,这是一个二维的部分最大值。由于之前写了球染色这道题,所以脑子里印象比较深刻,我们立马想用单调队列求出这个最大值,但是发现二维的不好维护,我就先维护了每一行的最大值,这样把一段区间加在一个点上,再竖着来一遍,就求出二维的最大值了。
typedef pair<int,int> P;int n,m,mi=2e9,mx;int h[M][M];ll sum[M][M];int Max[M][M];P que[M];int L,R;int T;int main(){ int a,b; Rd(n);Rd(m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ Rd(h[i][j]); mi=min(mi,h[i][j]); mx=max(mx,h[i][j]); sum[i][j]=sum[i-1][j-1]+sum[i][j-1]-sum[i-1][j-1]+sum[i-1][j]-sum[i-1][j-1]+h[i][j]; } Rd(T); while(T--){ memset(Max,0,sizeof(Max)); ll ans=2e18; Rd(a);Rd(b); for(int i=1;i<=n;i++){ L=R=0; for(int j=1;j<=m;j++){ while(L<R&&que[R-1].first<h[i][j])R--; que[R++]=P(h[i][j],j); while(L<R&&j-que[L].second>=b)L++; Max[i][j]=que[L].first; } } for(int j=b;j<=m;j++){ L=R=0; for(int i=1;i<=n;i++){ while(L<R&&que[R-1].first<Max[i][j])R--; que[R++]=P(Max[i][j],i); while(L<R&&i-que[L].second>=a)L++; Max[i][j]=que[L].first; } } for(int i=a;i<=n;i++) for(int j=b;j<=m;j++)//枚举右下角 ans=min(ans,1LL*a*b*Max[i][j]-(sum[i][j]-sum[i-a][j]-sum[i][j-b]+sum[i-a][j-b])); Pt(ans); putchar('\n'); } return 0;}
T2 Codechef JUNE16 刷副本
这道题的难点就在如何求首位了,考试的时候我敲了个高精,然后手贱数组开了50000,每次定义一次要
我们只要处理出每个数的
接下来是查询和更新操作了。对于查询,我们事先预处理出每种
int fast(int a,int p){ int res=1; while(p){ if(p&1)res=1LL*res*a%P; a=1LL*a*a%P; p>>=1; } return res;}int n,q;int A[M];int fac[M];double sum[M];vector<int>son[M];int main(){ int opr,x,f; Rd(n); for(int i=0;i<n;i++)Rd(A[i]); for(int i=1;i<=n;i++){ fac[i]=1; for(int j=i;j<n;j+=i){ fac[i]=1LL*fac[i]*A[j]%P; sum[i]+=log10(A[j]); son[j].push_back(i); } } Rd(q); while(q--){ Rd(opr); if(opr==1){ Rd(x);Rd(f);x--; if(x){ int pre=A[x]; double t=log10(pre); int tt=fast(pre,P-2); double ttt=log10(f); for(int i=0;i<son[x].size();i++){ int v=son[x][i]; sum[v]-=t; sum[v]+=ttt; fac[v]=1LL*fac[v]*tt%P*f%P; } } A[x]=f; }else{ Rd(x); int res=1LL*fac[x]*A[0]%P; double fi=sum[x]+log10(A[0]); int ans=(int)pow(10,fi-floor(fi)+eps); if(ans==10)ans=1; Pt(ans); putchar(' '); Pt(res); putchar('\n'); } } return 0;}
T3 USACO 2017 Open Platinum 圣杯战争
唉,这题考试时不知道怎么想的,敲了个
发现了这个性质,题目就好想了,我们不妨以1为根,对每个点建树,存下这个点到达每种颜色儿子的花费,由于内存开不下,我们可以采用动态造节点的方式,因为在最大数据中一个点能用到的儿子最多只有10个。对于一个节点的贡献,只要
#include<set>#include<stdio.h>#include<string.h>#include<algorithm>#include<iostream>#define M 200005#define oo 2000000000using namespace std;template <class T>inline void Rd(T &res){ char c;res=0;int k=1; while(c=getchar(),c<48&&c!='-'); if(c=='-'){k=-1;c='0';} do{ res=(res<<3)+(res<<1)+(c^48); }while(c=getchar(),c>=48); res*=k;}template <class T>inline void Pt(T res){ if(res<0){ putchar('\n'); res=-res; } if(res>=10)Pt(res/10); putchar(res%10+48);}struct ED{ int a,b,w; bool operator <(const ED &tmp)const{ return w<tmp.w; }}E[M<<1];struct edge{ int v,nxt,cost;}e[M<<1];multiset<int>ans,s[M<<2];int n,m,K,Q;int A[M],fa[M],pa[M],res[M],la[M];//pa存树上的fatherint rt[M],num[M*60],sz,lr[M*60],rr[M*60];int id[M*60],ct;int head[M],edgecnt;int get_fa(int v){ if(fa[v]==v)return v; return fa[v]=get_fa(fa[v]);}bool same(int u,int v){ return get_fa(u)==get_fa(v);}void merge(int u,int v){ int px=get_fa(u); int py=get_fa(v); fa[py]=px;}void add_edge(int u,int v,int cost){ e[++edgecnt].v=v;e[edgecnt].cost=cost;e[edgecnt].nxt=head[u];head[u]=edgecnt;}void up(int p){ num[p]=min(num[lr[p]],num[rr[p]]);}int query(int p,int L,int R,int l,int r){ if(!p||l>r)return oo; if(l==L&&r==R)return num[p]; int mid=(L+R)>>1; if(r<=mid)return query(lr[p],L,mid,l,r); if(l>mid)return query(rr[p],mid+1,R,l,r); return min(query(lr[p],L,mid,l,mid),query(rr[p],mid+1,R,mid+1,r));}void update(int &p,int L,int R,int x,int w,bool f){ if(!p){p=++sz;num[p]=oo;} if(L==R){ if(!id[p])id[p]=++ct; int now=id[p]; if(f)s[now].insert(w); else s[now].erase(s[now].find(w)); if(s[now].size())num[p]=*(s[now].begin()); else num[p]=oo; return; } int mid=(L+R)>>1; if(x<=mid)update(lr[p],L,mid,x,w,f); else update(rr[p],mid+1,R,x,w,f); up(p);}void dfs(int x,int t){ pa[x]=t; for(int i=head[x];~i;i=e[i].nxt){ int v=e[i].v; if(v==t)continue; dfs(v,x); res[v]=e[i].cost; update(rt[x],1,K,A[v],e[i].cost,1); } if(rt[x]){ la[x]=min(query(rt[x],1,K,1,A[x]-1),query(rt[x],1,K,A[x]+1,K)); ans.insert(la[x]); }}void Init(){ memset(head,-1,sizeof(head)); memset(pa,-1,sizeof(pa)); num[0]=oo; sort(E+1,E+m+1); for(register int i=1;i<=m;++i){ int u=E[i].a,v=E[i].b; if(!same(u,v)){ add_edge(u,v,E[i].w); add_edge(v,u,E[i].w); merge(u,v); } } dfs(1,-1);}int main(){ int x,k; Rd(n);Rd(m);Rd(K);Rd(Q); for(int i=1;i<=m;i++){ Rd(E[i].a);Rd(E[i].b);Rd(E[i].w); } for(int i=1;i<=n;i++){ Rd(A[i]); fa[i]=i; } Init(); while(Q--){ Rd(x);Rd(k); if(k!=A[x]){ if(rt[x]){ ans.erase(ans.find(la[x])); la[x]=min(query(rt[x],1,K,1,k-1),query(rt[x],1,K,k+1,K)); ans.insert(la[x]); } if(x!=1){ int f=pa[x]; ans.erase(ans.find(la[f])); update(rt[f],1,K,A[x],res[x],0); update(rt[f],1,K,k,res[x],1); la[f]=min(query(rt[f],1,K,1,A[f]-1),query(rt[f],1,K,A[f]+1,K)); ans.insert(la[f]); } A[x]=k; } Pt(*(ans.begin())); putchar('\n'); } return 0;}
T2的失算让我对
- 2017/8/7 离线赛
- 2017/8/5 离线赛
- 2017/8/9 离线赛
- 2017/8/11 离线赛
- 2017/8/14 离线赛
- 2017/8/19 离线赛
- 2017/8/20 离线赛
- 2017/8/26 离线赛
- 2017/7/15 离线赛
- 2017/7/24 离线赛
- 2017/7/27 离线赛
- 2017-10-8离线赛总结
- 2017-11-8离线赛总结
- 2017/7/29 离线赛 总结
- 2017-10-7离线赛题解
- 2017-10-7离线赛总结
- 2017-11-7离线赛总结
- 2017/9/2 离线赛
- Connection接口中isClosed() 和 isValid() 的区别
- POJ
- 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5
- Xamarin.Forms 多屏显示深度解析
- Codeforces Round #303 (Div. 2) B
- 2017/8/7 离线赛
- myeclipse中svn突然失效问题
- 用memset清空数组时要注意的问题
- Android获取手机存储状态
- 日常篇
- AOP通知类型
- F
- 递归 汉诺塔问题
- android.mk的配置说明