官方解题报告http://blog.sina.com.cn/s/blog_a19ad7a10102uyiq.html

Wow! Such Sequence! http://acm.hdu.edu.cn/showproblem.php?pid=4893

线段树,比赛时写的不好。

 #include<cstdio>
#include<algorithm>
#define lrrt int L,int R,int rt
#define iall 1,n,1
#define imid int mid=(L+R)>>1
#define lson L,mid,rt<<1
#define rson mid+1,R,rt<<1|1
using namespace std;
typedef __int64 LL;
const int M=;
struct T{
LL sum;
bool cover;
}tree[M<<];
LL F[M];
int Flen=;
void initF(){
F[]=F[]=;
for(int i=;i<Flen;i++){
F[i]=F[i-]+F[i-];
}
}
int Findcloseid(LL val){
if(val<=) return ;
int id=lower_bound(F,F+Flen,val)-F;
if(abs(F[id-]-val)<=abs(F[id]-val)) id--;
return id;
}
void pushup(int rt){
tree[rt].sum=tree[rt<<].sum+tree[rt<<|].sum;
tree[rt].cover=tree[rt<<].cover&tree[rt<<|].cover;
}
void build(lrrt){
tree[rt].cover=;
tree[rt].sum=;
if(L==R) return ;
imid;
build(lson);
build(rson);
}
void add(int x,int val,lrrt){
if(L==R){
tree[rt].sum+=val;
int id=Findcloseid(tree[rt].sum);
tree[rt].cover=(F[id]==tree[rt].sum);
return ;
}
imid;
if(mid>=x) add(x,val,lson);
else add(x,val,rson);
pushup(rt);
}
void update(int x,int y,lrrt){
if(L==R){
tree[rt].cover=true;
tree[rt].sum=F[Findcloseid(tree[rt].sum)];
return ;
}
imid;
if(x<=L&&R<=y){
if(tree[rt].cover) return ;
update(x,y,lson);
update(x,y,rson);
pushup(rt);
return ;
}
if(mid>=x) update(x,y,lson);
if(mid<y) update(x,y,rson);
pushup(rt);
}
LL query(int x,int y,lrrt){
if(x<=L&&R<=y) return tree[rt].sum;
imid;
LL ans=;
if(mid>=x) ans+=query(x,y,lson);
if(mid<y) ans+=query(x,y,rson);
return ans;
}
int main(){
initF();
int n,m;
while(~scanf("%d%d",&n,&m)){
build(iall);
while(m--){
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
if(op==){
add(x,y,iall);
}
else if(op==){
printf("%I64d\n",query(x,y,iall));
}
else{
update(x,y,iall);
}
}
}
return ;
}

Scary Path Finding Algorithm http://acm.hdu.edu.cn/showproblem.php?pid=4889

 #include<cstdio>
using namespace std;
int exp2[],c;
int main() {
exp2[] = ;
for(int i = ; i < ; i++) {
exp2[i] = exp2[i-] <<;
}
while(~scanf("%d",&c)) {
puts("61 90");
for(int i = ,j; i < ; i++) {
j=i<<;
printf("%d %d %d\n",+j,+j+,);
printf("%d %d %d\n",+j+,+j+, -exp2[-i]);
printf("%d %d %d\n",+j,+j+, -exp2[-i]);
}
}
return ;
}

The Great Pan http://acm.hdu.edu.cn/showproblem.php?pid=4891

模拟题。

 #include<cstdio>
#include<cstring>
typedef __int64 LL;
const int M=;
char a[M][M];
int main(){
int n;
while(~scanf("%d",&n)){
getchar();
for(int i=;i<n;i++){
gets(a[i]);
}
LL ans=;
LL sa=,sb=;// ||| ' '
bool fa=,fb=;
bool big=false;
for(int i=;i<n;i++){
if(big) break;
int len=strlen(a[i]);
for(int j=;j<len;j++){
if(big) break;
if(a[i][j]=='{'){
fa=true;
sa=;
}
else if(a[i][j]=='}'){
fa=false;
ans*=(sa+);
if(ans>) big=true;
sa=;
}
else if(a[i][j]=='$'){
if(fb){
fb=false;
ans*=(sb+);
sb=;
}
else{
fb=true;
sb=;
}
}
else{
if(fa){
if(a[i][j]=='|'){
sa++;
}
}
else if(fb){
if(a[i][j]==' '){
int k;
for(k=j;k<len;k++){
if(a[i][k]==' ') sb++;
else break;
}
j=k-;
if(k==len){
if(i+<n&&a[i+][]==' ')
continue;
}
ans*=(sb+);
if(ans>) big=true;
sb=;
}
}
}
}
}
if(big){
puts("doge");
continue;
}
printf("%I64d\n",ans);
}
return ;
}

Redraw Beautiful Drawings http://acm.hdu.edu.cn/showproblem.php?pid=4888

最大流建图和判断多解有待研究。

我们建一个二部图,左边是行,右边是列,建个源点与行建边,容量是该行的和,列与新建的汇点建边,容量是该列的和,最后每行与每列建边,容量为题意中的k。建边如图:

跑一遍最大流,如果最大流等于行的和且等于列的和,那么就是有解的,否则无解。这样我们得到了一组解,行i到列j的流量即为i行j列的大小。之后便是判断是否有多种情况了。基本思路是这样的,我们看下图:

有多解的情况一定可以找到这样的4个位置:AB同行,CD同行,AC同列,BD同列,并且他们符合一下两种情况的其中一种:
1、AD未达到k(可变大),BC不是0(可减小)
2、AD不是0(可减小),BC未达到k(可变大)

不过枚举的话复杂度太高了,这里需要优化下。我建了一个二维数组cc[i][j],代表之前行是否有第i个可变大,第j个可减小的情况。这里枚举每一行,每一行再枚举两个位置i和j,如果当前行有i和j使得第i可以减小、第j个可以变大并且cc[i][j]为1,那么一定有多解。这里如果cc[i][j]为0,那么继续,同时cc[j][i]赋为1。这样的话就避免了最坏O(400^4)的复杂度,而变成了最多O(400^3)。

 #include<cstdio>
#include<cstring>
#include<queue>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
const int inf=0x7fffffff;
const int M=;
class Sap { //最大流sap算法O(V*E^2)
int n,head[M],dep[M],gap[M],cur[M],S[M],res,top,i,inser;
queue<int> q;
void bfs(int s,int t) {
mt(dep,-);
mt(gap,);
while(!q.empty()) q.pop();
gap[]=;
dep[t]=;
q.push(t);
while(!q.empty()) {
int u=q.front();
q.pop();
for(int i=head[u]; ~i; i=e[i].next) {
int v=e[i].v;
if(dep[v]!=-) continue;
q.push(v);
dep[v]=dep[u]+;
++gap[dep[v]];
}
}
}
public:
struct E {
int u,v,next,flow;
} e[M*M];
int le;
void init(int tn) {
n=tn;
le=;
mt(head,-);
}
void add(int u,int v,int flow) {
e[le].u=u;
e[le].v=v;
e[le].flow=flow;
e[le].next=head[u];
head[u]=le++;
e[le].u=v;
e[le].v=u;
e[le].flow=;
e[le].next=head[v];
head[v]=le++;
}
int solve(int s,int t) {
bfs(s,t);
res=top=;
for(i=;i<=n;i++) cur[i]=head[i];
int u=s;
while(dep[s]<n) {
if(u==t) {
int temp=inf;
for(i=; i<top; i++)
if(temp>e[S[i]].flow) {
temp=e[S[i]].flow;
inser=i;
}
for(i=; i<top; i++) {
e[S[i]].flow-=temp;
e[S[i]^].flow+=temp;
}
res+=temp;
top=inser;
u=e[S[top]].u;
}
if(u!=t&&!gap[dep[u]-]) break;
for(i=cur[u]; ~i; i=e[i].next)
if(e[i].flow&&dep[u]==dep[e[i].v]+)
break;
if(~i) {
cur[u]=i;
S[top++]=i;
u=e[i].v;
} else {
int sma=n;
for(i=head[u]; ~i; i=e[i].next) {
if(!e[i].flow) continue;
if(sma>dep[e[i].v]) {
sma=dep[e[i].v];
cur[u]=i;
}
}
--gap[dep[u]];
dep[u]=sma+;
++gap[dep[u]];
if(u!=s) u=e[S[--top]].u;
}
}
return res;
}
} gx;
int n,m,k,suma,sumb,a[M>>],b[M>>],mp[M>>][M>>];
bool dou[M>>][M>>];//dou[0][i] i这列存在一个可增的点
int solve(){
if(suma!=sumb) return -;
int s=,t=n+m+;
gx.init(t+);
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
gx.add(i,j+n,k);
}
}
for(int i=;i<=n;i++){
gx.add(s,i,a[i]);
}
for(int i=;i<=m;i++){
gx.add(i+n,t,b[i]);
}
if(gx.solve(s,t)!=suma) return -;
int eid=;
for(int i=;i<=n;i++){
for(int j=;j<=m;j++,eid+=){
mp[i][j]=gx.e[eid].flow;
}
}
mt(dou,);
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
for(int z=j+;z<=m;z++){
bool v1=false,v2=false;
if(mp[i][j]!=k&&mp[i][z]!=){
if(dou[z][j]) return ;
v1=;
}
if(mp[i][j]!=&&mp[i][z]!=k){
if(dou[j][z]) return ;
v2=;
}
if(v1) dou[j][z]=true;
if(v2) dou[z][j]=true;
}
}
}
return ;
}
int main(){
while(~scanf("%d%d%d",&n,&m,&k)){
suma=sumb=;
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
suma+=a[i];
}
for(int i=;i<=m;i++){
scanf("%d",&b[i]);
sumb+=b[i];
}
int ans=solve();
if(ans==-){
puts("Impossible");
}
else if(!ans){
puts("Not Unique");
}
else{
puts("Unique");
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if(j>) printf(" ");
printf("%d",mp[i][j]);
}
puts("");
}
}
}
}

李队随机法选点测试,随机100次能ac。佩服。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
const int inf=0x7fffffff;
const int M=;
class Sap { //最大流sap算法O(V*E^2)
int n,head[M],dep[M],gap[M],cur[M],S[M],res,top,i,inser;
queue<int> q;
void bfs(int s,int t) {
mt(dep,-);
mt(gap,);
while(!q.empty()) q.pop();
gap[]=;
dep[t]=;
q.push(t);
while(!q.empty()) {
int u=q.front();
q.pop();
for(int i=head[u]; ~i; i=e[i].next) {
int v=e[i].v;
if(dep[v]!=-) continue;
q.push(v);
dep[v]=dep[u]+;
++gap[dep[v]];
}
}
}
public:
struct E {
int u,v,next,flow;
} e[M*M];
int le;
void init(int tn) {
n=tn;
le=;
mt(head,-);
}
void add(int u,int v,int flow) {
e[le].u=u;
e[le].v=v;
e[le].flow=flow;
e[le].next=head[u];
head[u]=le++;
e[le].u=v;
e[le].v=u;
e[le].flow=;
e[le].next=head[v];
head[v]=le++;
}
int solve(int s,int t) {
bfs(s,t);
res=top=;
for(i=;i<=n;i++) cur[i]=head[i];
int u=s;
while(dep[s]<n) {
if(u==t) {
int temp=inf;
for(i=; i<top; i++)
if(temp>e[S[i]].flow) {
temp=e[S[i]].flow;
inser=i;
}
for(i=; i<top; i++) {
e[S[i]].flow-=temp;
e[S[i]^].flow+=temp;
}
res+=temp;
top=inser;
u=e[S[top]].u;
}
if(u!=t&&!gap[dep[u]-]) break;
for(i=cur[u]; ~i; i=e[i].next)
if(e[i].flow&&dep[u]==dep[e[i].v]+)
break;
if(~i) {
cur[u]=i;
S[top++]=i;
u=e[i].v;
} else {
int sma=n;
for(i=head[u]; ~i; i=e[i].next) {
if(!e[i].flow) continue;
if(sma>dep[e[i].v]) {
sma=dep[e[i].v];
cur[u]=i;
}
}
--gap[dep[u]];
dep[u]=sma+;
++gap[dep[u]];
if(u!=s) u=e[S[--top]].u;
}
}
return res;
}
} gx;
int n,m,k,suma,sumb,a[M>>],b[M>>],mp[M>>][M>>];
int solve(){
if(suma!=sumb) return -;
int s=,t=n+m+;
gx.init(t+);
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
gx.add(i,j+n,k);
}
}
for(int i=;i<=n;i++){
gx.add(s,i,a[i]);
}
for(int i=;i<=m;i++){
gx.add(i+n,t,b[i]);
}
if(gx.solve(s,t)!=suma) return -;
int eid=;
for(int i=;i<=n;i++){
for(int j=;j<=m;j++,eid+=){
mp[i][j]=gx.e[eid].flow;
}
}
bool ok=false; //李队随机法过
if(n!=&&m!=){
for(int t=; t<=; t++) { //随机100次就能找到 数据不强?
int i=rand()%(n-)+;
int j=rand()%(m-)+;
int ii=rand()%(n-i)++i;
int jj=rand()%(m-j)++j;
int lu=mp[i][j];
int ld=mp[ii][j];
int ru=mp[i][jj];
int rd=mp[ii][jj];
if(lu>&&rd>&&ld<k&&ru<k)ok=true;
if(lu<k&&rd<k&&ld>&&ru>)ok=true;
if(ok)break;
}
}
if(ok) return ;
return ;
}
int main(){
while(~scanf("%d%d%d",&n,&m,&k)){
suma=sumb=;
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
suma+=a[i];
}
for(int i=;i<=m;i++){
scanf("%d",&b[i]);
sumb+=b[i];
}
int ans=solve();
if(ans==-){
puts("Impossible");
}
else if(!ans){
puts("Not Unique");
}
else{
puts("Unique");
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if(j>) printf(" ");
printf("%d",mp[i][j]);
}
puts("");
}
}
}
}

从源点向行连容量为行总和的边,从列向汇点连容量为列总和的边,从行->列连容量为K的边。这样跑出最大流,如果是满流就有解。判断多解就是判断最大流是否有多解。在残留网络中,如果能找到一个环,那么流量就可以从这个环绕一圈,而不改变最大流。这个dfs一下就好了。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#define mt(a,b) memset(a,b,sizeof(a))
using namespace std;
const int inf=0x7fffffff;
const int M=;
class Sap { //最大流sap算法O(V*E^2)
int n,dep[M],gap[M],cur[M],S[M],res,top,i,inser;
queue<int> q;
void bfs(int s,int t) {
mt(dep,-);
mt(gap,);
while(!q.empty()) q.pop();
gap[]=;
dep[t]=;
q.push(t);
while(!q.empty()) {
int u=q.front();
q.pop();
for(int i=head[u]; ~i; i=e[i].next) {
int v=e[i].v;
if(dep[v]!=-) continue;
q.push(v);
dep[v]=dep[u]+;
++gap[dep[v]];
}
}
}
public:
struct E {
int u,v,next,flow;
} e[M*M];
int le,head[M];
void init(int tn) {
n=tn;
le=;
mt(head,-);
}
void add(int u,int v,int flow) {
e[le].u=u;
e[le].v=v;
e[le].flow=flow;
e[le].next=head[u];
head[u]=le++;
e[le].u=v;
e[le].v=u;
e[le].flow=;
e[le].next=head[v];
head[v]=le++;
}
int solve(int s,int t) {
bfs(s,t);
res=top=;
for(i=;i<=n;i++) cur[i]=head[i];
int u=s;
while(dep[s]<n) {
if(u==t) {
int temp=inf;
for(i=; i<top; i++)
if(temp>e[S[i]].flow) {
temp=e[S[i]].flow;
inser=i;
}
for(i=; i<top; i++) {
e[S[i]].flow-=temp;
e[S[i]^].flow+=temp;
}
res+=temp;
top=inser;
u=e[S[top]].u;
}
if(u!=t&&!gap[dep[u]-]) break;
for(i=cur[u]; ~i; i=e[i].next)
if(e[i].flow&&dep[u]==dep[e[i].v]+)
break;
if(~i) {
cur[u]=i;
S[top++]=i;
u=e[i].v;
} else {
int sma=n;
for(i=head[u]; ~i; i=e[i].next) {
if(!e[i].flow) continue;
if(sma>dep[e[i].v]) {
sma=dep[e[i].v];
cur[u]=i;
}
}
--gap[dep[u]];
dep[u]=sma+;
++gap[dep[u]];
if(u!=s) u=e[S[--top]].u;
}
}
return res;
}
} gx;
int n,m,k,suma,sumb,a[M>>],b[M>>],mp[M>>][M>>];
bool vis[M];
bool dfs(int u,int fa){
for(int i=gx.head[u];~i;i=gx.e[i].next){
int w=gx.e[i].flow;
if(w==) continue;
int v=gx.e[i].v;
if(v!=fa){
if(vis[v]) return true;
vis[v]=true;
if(dfs(v,u)) return true;
vis[v]=false;
}
}
return false;
}
int solve(){
if(suma!=sumb) return -;
int s=,t=n+m+;
gx.init(t+);
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
gx.add(i,j+n,k);
}
}
for(int i=;i<=n;i++){
gx.add(s,i,a[i]);
}
for(int i=;i<=m;i++){
gx.add(i+n,t,b[i]);
}
if(gx.solve(s,t)!=suma) return -;
int eid=;
for(int i=;i<=n;i++){
for(int j=;j<=m;j++,eid+=){
mp[i][j]=gx.e[eid].flow;
}
}
mt(vis,);
for(int i=;i<=n;i++){
if(dfs(i,-)){
return ;
}
}
return ;
}
int main(){
while(~scanf("%d%d%d",&n,&m,&k)){
suma=sumb=;
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
suma+=a[i];
}
for(int i=;i<=m;i++){
scanf("%d",&b[i]);
sumb+=b[i];
}
int ans=solve();
if(ans==-){
puts("Impossible");
}
else if(!ans){
puts("Not Unique");
}
else{
puts("Unique");
for(int i=;i<=n;i++){
for(int j=;j<=m;j++){
if(j>) printf(" ");
printf("%d",mp[i][j]);
}
puts("");
}
}
}
}

end

2014 Multi-University Training Contest 3的更多相关文章

  1. 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 ...

  2. 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) ...

  3. 2014 Multi-University Training Contest 9#11

    2014 Multi-University Training Contest 9#11 Killing MonstersTime Limit: 2000/1000 MS (Java/Others)   ...

  4. 2014 Multi-University Training Contest 9#6

    2014 Multi-University Training Contest 9#6 Fast Matrix CalculationTime Limit: 2000/1000 MS (Java/Oth ...

  5. 2014 Multi-University Training Contest 1/HDU4861_Couple doubi(数论/法)

    解题报告 两人轮流取球,大的人赢,,, 贴官方题解,,,反正我看不懂.,,先留着理解 关于费马小定理 关于原根 找规律找到的,,,sad,,, 非常easy找到循环节为p-1,每个循环节中有一个非零的 ...

  6. 2014 Multi-University Training Contest 1/HDU4864_Task(贪心)

    解题报告 题意,有n个机器.m个任务. 每一个机器至多能完毕一个任务.对于每一个机器,有一个最大执行时间Ti和等级Li,对于每一个任务,也有一个执行时间Tj和等级Lj.仅仅有当Ti>=Tj且Li ...

  7. hdu 4937 2014 Multi-University Training Contest 7 1003

    Lucky Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) T ...

  8. hdu 4941 2014 Multi-University Training Contest 7 1007

    Magical Forest Time Limit: 24000/12000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Other ...

  9. hdu 4939 2014 Multi-University Training Contest 7 1005

    Stupid Tower Defense Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/ ...

  10. hdu 4930 Fighting the Landlords--2014 Multi-University Training Contest 6

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4930 Fighting the Landlords Time Limit: 2000/1000 MS ...

随机推荐

  1. 【学习笔记】【C语言】变量类型

    根据变量的作用域,可以分为: 1.局部变量: 1> 定义:在函数(代码块)内部定义的变量(包括函数的形参) 2> 作用域:从定义变量的那一行开始,一直到代码块结束 3> 生命周期:从 ...

  2. UI4_UIWebView

    // // ViewController.m // UI4_UIWebView // // Created by zhangxueming on 15/7/7. // Copyright (c) 20 ...

  3. C语言清除输入缓存方法记录[转]

    原文:http://www.tomytime.com/archives/218/ fflush()函数是标准的作法. setbuf(stdin,NULL)是GCC下可用的一种方法. scanf(&qu ...

  4. Angularjs入门学习一 简介

    本系列文章是从头开始学习angularjs,下文中用ng表示angularjs,要知道从以为根深蒂固的jquery开发者转变开发思想,确实需要一段时间,下面介绍以下 angularjs,我也是参考网上 ...

  5. python 实现梯度下降

    在多元线性回归中会用到梯度下降来计算参数值.这里我用python实现一个梯度下降版本. 这里多元线性方程为 y = A0+A1*x1+...+An* xn 数据输入格式,y表示 y \t x1 \t ...

  6. SecureCRT远程控制ubuntu

    如果你拥有两台电脑一台是ubuntu,另一台是笔记本电脑,而你又想在远程控制你的ubuntu,那么SecureCRT就可以用了. 1:首先在你的ubuntu电脑上安装SSH服务  :apt-get i ...

  7. linux 网桥的配置与实现

    ==================================================================================from: http://www.i ...

  8. javascript面向对象--自定义类型

    Javascript是基于原型实现面向对象的,因此并没有类和接口,它的对象也与其他基于类的语言中的对象有所不同.在Javascript中,每个对象都是基于一个引用类型创建的,这个引用类型可以是原生类型 ...

  9. liunx下vi命令详解

    vi编辑器是所有Unix及Linux系统下标准的编辑器,它的强大不逊色于任何最新的文本编辑器,这里只是简单地介绍一下它的用法和一小部分指令.由于对Unix及Linux系统的任何版本,vi编辑器是完全相 ...

  10. Docs list

    http://www.deansys.com/doc/ldd3/index.html Github中文文档: http://www.worldhello.net/gotgithub/03-projec ...