2011 Multi-University Training Contest 8 - Host by HUST
Rank:56/147.
开场看B,是个线段树区间合并,花了2hour敲完代码。。。再花了30min查错。。发现push_down有问题。改了就AC了。
然后发现A过了很多人。推了个公式,发现是个分段函数。取个中间点代进去结果就AC了。
C好像也很水?看了看原来是个傻逼BFS。A了。
F化解了一下就 集合子集异或为0的种数。想了想没想到什么东西就go die了。
A.Liang Guo Sha(阅读理解)
看懂题意后搞出两个式子,然后取个极值就行了。
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
}
const int N=;
//Code begin... int main ()
{
int a, b, c;
while (~scanf("%d%d%d",&a,&b,&c)){
double p=((b+c)*1.0)/(a+b+*c);
double ans=a*p*p+b*(-p)*(-p)-c*(-p)*p*;
printf("%.6f\n",ans);
}
return ;
}
B.Black And White(线段树)
询问区间[l,r]的最长连续黑色的长度。
建立线段树,对每个节点维护6个量,分别表示最长连续黑色,最长连续白色,左边最长连续黑色,左边最长连续白色,右边最长连续黑色,右边最长连续白色。
对于修改操作用tag标记一下。在需要push_down的时候push_down即可AC。
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
}
const int N=;
//Code begin... struct SegTree{int lbmax, lwmax, rbmax, rwmax, bmax, wmax;}seg[N<<];
struct Node{
int lmax, rmax, ma, siz;
Node(int _lmax=, int _rmax=, int _ma=, int _siz=):lmax(_lmax), rmax(_rmax), ma(_ma), siz(_siz){}
};
int a[N];
bool tag[N<<]; void push_up(int p, int l, int r){
int lsize=(l+r)/-l+, rsize=r-(l+r)/;
if (seg[p<<].lbmax) {
seg[p].lbmax=(seg[p<<].lbmax==lsize?seg[p<<|].lbmax:)+seg[p<<].lbmax;
seg[p].lwmax=;
}
else {
seg[p].lwmax=(seg[p<<].lwmax==lsize?seg[p<<|].lwmax:)+seg[p<<].lwmax;
seg[p].lbmax=;
}
if (seg[p<<|].rbmax) {
seg[p].rbmax=(seg[p<<|].rbmax==rsize?seg[p<<].rbmax:)+seg[p<<|].rbmax;
seg[p].rwmax=;
}
else {
seg[p].rwmax=(seg[p<<|].rwmax==rsize?seg[p<<].rwmax:)+seg[p<<|].rwmax;
seg[p].rbmax=;
}
seg[p].bmax=max(max(seg[p<<].bmax,seg[p<<|].bmax),seg[p<<].rbmax+seg[p<<|].lbmax);
seg[p].wmax=max(max(seg[p<<].wmax,seg[p<<|].wmax),seg[p<<].rwmax+seg[p<<|].lwmax);
}
void push_down(int p){
if (!tag[p]) return ;
tag[p<<]^=; tag[p<<|]^=; tag[p]=;
swap(seg[p].bmax,seg[p].wmax); swap(seg[p].lbmax,seg[p].lwmax); swap(seg[p].rbmax,seg[p].rwmax);
}
void init(int p, int l, int r){
if (l<r) {
int mid=(l+r)>>;
init(lch); init(rch); push_up(p,l,r); tag[p]=;
}
else {
if (a[l]) seg[p].lbmax=seg[p].rbmax=seg[p].bmax=, seg[p].lwmax=seg[p].rwmax=seg[p].wmax=;
else seg[p].lwmax=seg[p].rwmax=seg[p].wmax=, seg[p].lbmax=seg[p].rbmax=seg[p].bmax=;
tag[p]=;
}
}
void update(int p, int l, int r, int L, int R){
push_down(p);
if (L>r||R<l) return ;
if (L<=l&&R>=r) tag[p]=, push_down(p);
else {
int mid=(l+r)>>;
update(lch,L,R); update(rch,L,R); push_up(p,l,r);
}
}
Node query(int p, int l, int r, int L, int R){
push_down(p);
if (L>r||R<l) return Node(,,,);
if (L<=l&&R>=r) return Node(seg[p].lbmax,seg[p].rbmax,seg[p].bmax,r-l+);
int mid=(l+r)>>;
Node x=query(lch,L,R), y=query(rch,L,R), z;
z.lmax=(x.lmax==x.siz?y.lmax:)+x.lmax; z.rmax=(y.rmax==y.siz?x.rmax:)+y.rmax;
z.ma=max(max(x.ma,y.ma),x.rmax+y.lmax); z.siz=x.siz+y.siz;
return z;
}
int main ()
{
int n, m, flag, l, r;
while (~scanf("%d",&n)) {
FOR(i,,n) scanf("%d",a+i);
init(,,n);
scanf("%d",&m);
FOR(i,,m) {
scanf("%d%d%d",&flag,&l,&r);
if (flag) update(,,n,l,r);
else {
printf("%d\n",query(,,n,l,r).ma);
}
}
}
return ;
}
C.Turn Right(BFS)
题目保证一定存在起点到终点的路径。如果把终点给封死,那么从起点bfs一次再回到起点就行了。沿途统计所有标记。
这题的节点状态与普通的不同,需要定义vis[i][j]表示到点i是以j方向到的。然后对于每个方向会有一个优先级。即总是turn right。
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
}
const int N=;
//Code begin... int vis[N][N][], row[N][N], col[N][N];
int ps[][]={{,,,},{,,,},{,,,},{,,,}}; struct Node{
int x, y, pos;
Node(int _x=, int _y=, int _pos=):x(_x),y(_y),pos(_pos){}
};
queue<Node>Q; int main ()
{
int T, n, m, s, t;
scanf("%d",&T);
while (T--) {
int num=;
mem(vis,);
scanf("%d%d%d%d",&n,&m,&s,&t);
FOR(i,,*n-) {
if (i&) FO(j,,m-) scanf("%d",&col[(i-)/][j]);
else FO(j,,m) scanf("%d",&row[i/][j]);
}
while (!Q.empty()) Q.pop();
Q.push(Node(,s,)); vis[][s][]=;
while (!Q.empty()) {
Node tmp=Q.front(); Q.pop();
FO(i,,) {
int now=ps[tmp.pos][i];
if (now==) {
if (tmp.y==||col[tmp.x][tmp.y-]) continue;
if (vis[tmp.x][tmp.y-][now]) goto label;
Q.push(Node(tmp.x,tmp.y-,now));
vis[tmp.x][tmp.y-][now]=;
break;
}
else if (now==) {
if (tmp.x==n-||row[tmp.x+][tmp.y]) continue;
if (vis[tmp.x+][tmp.y][now]) goto label;
Q.push(Node(tmp.x+,tmp.y,now));
vis[tmp.x+][tmp.y][now]=;
break;
}
else if (now==) {
if (tmp.y==m-||col[tmp.x][tmp.y]) continue;
if (vis[tmp.x][tmp.y+][now]) goto label;
Q.push(Node(tmp.x,tmp.y+,now));
vis[tmp.x][tmp.y+][now]=;
break;
}
else {
if (tmp.x==||row[tmp.x][tmp.y]) continue;
if (vis[tmp.x-][tmp.y][now]) goto label;
Q.push(Node(tmp.x-,tmp.y,now));
vis[tmp.x-][tmp.y][now]=;
break;
}
}
}
label: FO(i,,n) FO(j,,m) FO(k,,) if (vis[i][j][k]) {++num; break;}
puts(num==n*m?"YES":"NO");
}
return ;
}
F.Game(高斯消元)
要想去除某些石堆使得先手必败。那么s[i]^s[i+1]^...s[n]=0.即问题转化为求出集合S的子集异或和为0的子集种数。
集合S里的每个数,要么选要么不选,考虑每一位的贡献,那么选了这个数,这个数上二进制位为1的位会贡献1.
于是对于每位,建立异或方程组,再用高斯消元求解这个方程的自由变元的数量即可。
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
}
const int N=;
//Code begin... int equ, var, a[][N]; LL pow_mod(LL a, LL n, LL mod){
LL ret=, temp=a%mod;
while (n) {
if (n&) ret=ret*temp%mod;
temp=temp*temp%mod;
n>>=;
}
return ret;
}
int Guass(){
int row, col;
for(row=,col=; row<equ&&col<var; ++col,++row){
int max_r=row;
FO(i,row+,equ) {
if(a[row][col]==) break;
if(a[max_r][col]<a[i][col]){max_r=i; break;}
}
if(max_r!=row) FOR(j,,var) swap(a[max_r][j],a[row][j]);
if(a[row][col]==) row--;
FO(i,row+,equ) {
if(a[i][col]==) continue;
FOR(j,col,var) a[i][j]^=a[row][j];
}
}
FO(i,row,equ) if(a[i][col]) return -;
return var-row;
}
int main ()
{
int T, n, val;
scanf("%d",&T);
while (T--) {
mem(a,);
scanf("%d",&n);
equ=; var=n;
FO(i,,n) {
scanf("%d",&val);
FO(j,,equ) a[j][i]=val%, val/=;
}
FO(j,,equ) a[j][n]=;
int b=Guass();
printf("%lld\n",pow_mod(,b,MOD));
}
return ;
}
G.Sequence Decomposition(贪心+树状数组)
给出一个序列,每次可以将连续的一段都减去1,每次操作的长度定义为连续段的长度,问最后使得序列都变为0时,最短的操作长度最长是多少。
首先,将操作改变顺序是不影响答案的。不妨从左端点1开始,依次向后看右端点的最佳选值.
如果有a[i]<=a[i+1],那么右端点就可以从i拓展到i+1了。如果有a[i]>a[i+1].那么右端点就不能再继续拓展了。反证证明这个贪心的正确性。
但是如果直接模拟操作的话显然是超时的。注意到每次的操作实际上是区间减,查询单点。可以用树状数组维护。
复杂度O(nlogn).
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
}
const int N=;
//Code begin... int a[N], tree[N], n; void add(int x, int val){while (x<=n+) tree[x]+=val, x+=lowbit(x);}
int query(int x){
int res=;
while (x) res+=tree[x], x-=lowbit(x);
return res;
}
int main ()
{
int T, ans;
scanf("%d",&T);
while (T--) {
mem(tree,); ans=INF;
scanf("%d",&n);
FOR(i,,n) scanf("%d",a+i), add(i,a[i]), add(i+,-a[i]);
a[n+]=;
int now=;
FOR(i,,n) {
if (a[i]<=a[i+]) continue;
int tmp=a[i]-a[i+];
add(now,-tmp); add(i+,tmp);
FOR(j,now,i) if (query(j)>=) {ans=min(i-j+,ans); now=j; break;}
}
printf("%d\n",ans);
}
return ;
}
H.Road constructions(最大权闭合子图)
裸题。。。不明白考试为啥不看。。。
# include <cstdio>
# include <cstring>
# include <cstdlib>
# include <iostream>
# include <vector>
# include <queue>
# include <stack>
# include <map>
# include <set>
# include <cmath>
# include <algorithm>
using namespace std;
# define lowbit(x) ((x)&(-x))
# define pi acos(-1.0)
# define eps 1e-
# define MOD
# define INF
# define mem(a,b) memset(a,b,sizeof(a))
# define FOR(i,a,n) for(int i=a; i<=n; ++i)
# define FO(i,a,n) for(int i=a; i<n; ++i)
# define bug puts("H");
# define lch p<<,l,mid
# define rch p<<|,mid+,r
# define mp make_pair
# define pb push_back
typedef pair<int,int> PII;
typedef vector<int> VI;
# pragma comment(linker, "/STACK:1024000000,1024000000")
typedef long long LL;
int Scan() {
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
void Out(int a) {
if(a<) {putchar('-'); a=-a;}
if(a>=) Out(a/);
putchar(a%+'');
}
const int N=;
//Code begin... struct Edge{int p, next, w;}edge[];
struct Node{int pre, suc, w, id;}node[];
int head[N], cnt=, s, t, vis[N];
int val[N];
queue<int>Q; void add_edge(int u, int v, int w){
edge[cnt].p=v; edge[cnt].w=w; edge[cnt].next=head[u]; head[u]=cnt++;
edge[cnt].p=u; edge[cnt].w=; edge[cnt].next=head[v]; head[v]=cnt++;
}
int bfs(){
int i, v;
mem(vis,-);
vis[s]=; Q.push(s);
while (!Q.empty()) {
v=Q.front(); Q.pop();
for (i=head[v]; i; i=edge[i].next) {
if (edge[i].w> && vis[edge[i].p]==-) {
vis[edge[i].p]=vis[v] + ;
Q.push(edge[i].p);
}
}
}
return vis[t]!=-;
}
int dfs(int x, int low){
int i, a, temp=low;
if (x==t) return low;
for (i=head[x]; i; i=edge[i].next) {
if (edge[i].w> && vis[edge[i].p]==vis[x]+){
a=dfs(edge[i].p,min(edge[i].w,temp));
temp-=a; edge[i].w-=a; edge[i^].w += a;
if (temp==) break;
}
}
if (temp==low) vis[x]=-;
return low-temp;
}
void init(){mem(head,); mem(val,); cnt=;}
int main ()
{
int n, m, k;
while (scanf("%d%d",&n,&m), n+m) {
int res=, sum=, tmp;
s=; t=m+; init();
FOR(i,,m) scanf("%d",&tmp), res+=tmp, add_edge(s,i,tmp);
scanf("%d",&k);
FOR(i,,k) scanf("%d%d%d%d",&node[i].pre,&node[i].suc,&node[i].id,&node[i].w), val[node[i].id]+=node[i].w;
FOR(i,,k) FOR(j,i+,k) {
if (node[i].id==node[j].id) continue;
if (node[i].suc==node[j].pre) add_edge(node[i].id,node[j].id,INF);
else if (node[i].pre==node[j].suc) add_edge(node[j].id,node[i].id,INF);
}
FOR(i,,m) add_edge(i,t,val[i]);
while (bfs()) while (tmp=dfs(s,INF)) sum+=tmp;
printf("%d\n",res-sum);
}
return ;
}
2011 Multi-University Training Contest 8 - Host by HUST的更多相关文章
- 2011 Multi-University Training Contest 1 - Host by HNU
A.A + B problem(待填坑) B.Cat VS Dog(二分图匹配) 喜欢cat和喜欢dog的人构成了二分图,如果两个人有冲突则连一条边,则问题转化为二分图最大点独立集问题.ans=n-最 ...
- 2011 Multi-University Training Contest 7 - Host by ECNU
AC: F I. rank 40/88. 开场看了F发现是个简单的DP,随便写了一下WA,,,发现把样例倒着输就过不了了...原来是忘了最后的时候开始上课的话可能上不了多久... 想到一个简洁的状态方 ...
- 2011 Multi-University Training Contest 6 - Host by JLU
打了4hours,做出一道题...太菜了.rank:45/107 开场看B,题目看不懂...3hours半才发现i<=N-1,不是i<=x-1.然而还是不会. 看到J有人过了,发现是个简单 ...
- 2011 Multi-University Training Contest 4 - Host by SDU
A.Color the Simple Cycle(polya计数+字符串匹配) 此题的难点在于确定置换的个数,由a[i+k]=a[i], e[i+k]=e[i]联想到KMP. 于是把原串和原串扩大两倍 ...
- 2015 UESTC Winter Training #8【The 2011 Rocky Mountain Regional Contest】
2015 UESTC Winter Training #8 The 2011 Rocky Mountain Regional Contest Regionals 2011 >> North ...
- HDU4888 Redraw Beautiful Drawings(2014 Multi-University Training Contest 3)
Redraw Beautiful Drawings Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- HDU 2018 Multi-University Training Contest 3 Problem A. Ascending Rating 【单调队列优化】
任意门:http://acm.hdu.edu.cn/showproblem.php?pid=6319 Problem A. Ascending Rating Time Limit: 10000/500 ...
- 2015 Multi-University Training Contest 8 hdu 5390 tree
tree Time Limit: 8000ms Memory Limit: 262144KB This problem will be judged on HDU. Original ID: 5390 ...
- hdu 4946 2014 Multi-University Training Contest 8
Area of Mushroom Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) ...
随机推荐
- ORB-SLAM(九)LocalMapping
LocalMapping作用是将Tracking中送来的关键帧放在mlNewKeyFrame列表中:处理新关键帧,地图点检查剔除,生成新地图点,Local BA,关键帧剔除.主要工作在于维护局部地图, ...
- python——一些常用的方法类
测试的时候经常需要使用一些方法都整理放在一起,方便调用 首先一些基本的配置引入 localReadConfig = readConfig.ReadConfig() proDir = readConfi ...
- mysql新手进阶03
当年忠贞为国酬,何曾怕断头? 如今天下红遍,江山靠谁守? 业未就,身躯倦,鬓已秋. 你我之辈,忍将夙愿,付与东流? 数据库结构如下: 仓库(仓库号, 城市, 面积) 订购单(职工号, 供应商号, 订购 ...
- Unity初探—SpaceShoot
Unity初探—SpaceShoot DestroyByBoundary脚本(C#) 在游戏中我们添加了一个Cube正方体,让他来作为游戏的边界.它是可以触发触发事件的(勾选Is Trigger),当 ...
- linux学习总结----mongoDB总结
dbhelper.py 用户登录和注册(加密算法) 加密导包 import hashlib 或者使用Md5 加密 MongoDB ->JSON service mysql start servi ...
- 树的层次遍历(Trees on the level,UVA 122)
题目描述: 题目思路: 1.用结构链表来建树 2.用队列来实现层次遍历,当遍历到根节点时,将其子节点压入队列 #include <iostream> #include <cstdli ...
- Maven编译Java项目
Spring在线参考文档: http://spring.io/guides/gs/maven/ 下载安装 Downloadand unzip the source repository for thi ...
- Java内存管理特点
Java内存管理特点 Java一个最大的优点就是取消了指针,由垃圾收集器来自动管理内存的回收.程序员不需要通过调用函数来释放内存. 1.Java的内存管理就是对象的分配和释放问题. 在 ...
- 3.azkaban3.0测试
测试目标 azkaban多executor下flow的分配方式 azkaban可以同时执行的flow\job个数 azkaban单个job最小使用的内存 相关配置 executor最大线程数: exe ...
- Hadoop之block研究
本文翻译原链接:https://hadoopabcd.wordpress.com/2015/03/17/hdfs-file-blocks-distribution-in-datanodes/ ...