ZOJ 刷题记录 (。・ω・)ノ゙(Progress:31/50)
【热烈庆祝ZOJ回归】
P1002:简单的DFS
#include <cstdio>
#include <cstring>
#include <algorithm>
][];
int N;
int input()
{
scanf("%d",&N);
;i<N;i++) scanf("%s",map[i]);
return N;
}
][];
,sizeof(disable)); }
int dfs(int cur)
{
)
][N-]>- || map[N-][N-]== : ;
int c = cur / N;
int r = cur % N;
)
);
);
for(int i=c;i<N && map[i][r]=='.';i++)
) disable[i][r]=cur;
for(int j=r;j<N && map[c][j]=='.';j++)
) disable[c][j]=cur;
res=std::max(res,dfs(cur+)+);
for(int i=c;i<N && map[i][r]=='.';i++)
;
for(int j=r;j<N && map[c][j]=='.';j++)
;
return res;
}
//cur=N*c+r
int main()
{
while(input())
{
init();
printf());
}
;
}
Problem:ZOJ P1002
P1005:简单的DFSx2(Orz排行榜里那些28K的,我太弱所以用了1236K( ̄▽ ̄"))
另外不要吐槽人家丑陋的代码٩(×̯×)۶
#include <cstdio>
#include <cstring>
#include <algorithm>
int A,B,N;
bool input()
{
return scanf("%d%d%d",&A,&B,&N)!=EOF;
}
][];
const char str_success[]="success";
const char str_pour[]="pour";
const char str_empty[]="empty";
const char str_fill[]="fill";
struct Cmd
{
const char* cmdType;
char v1,v2;
Cmd(const char* _cmd,char _v1,char _v2):
cmdType(_cmd),v1(_v1),v2(_v2) {}
void output()
{
if(cmdType==str_success) printf("%s\n",str_success);
else if(cmdType==str_pour) printf("%s %c %c\n",str_pour,v1,v2);
else if(cmdType==str_fill) printf("%s %c\n",str_fill,v1);
else printf("%s %c\n",str_empty,v1);
}
};
#include <stack>
std::stack<Cmd> dfsStack;
void init()
{
memset(ins,,sizeof(ins));
}
bool dfs(int a,int b)
{
ins[a][b]=true;
if(b==N)
{
dfsStack.push(Cmd(str_success,'a','a'));
return true;
}
][b] && dfs(,b))
{
dfsStack.push(Cmd(str_empty,'A','A'));
return true;
}
] && dfs(a,))
{
dfsStack.push(Cmd(str_empty,'B','B'));
return true;
}
if(a<A && !ins[A][b] && dfs(A,b))
{
dfsStack.push(Cmd(str_fill,'A','A'));
return true;
}
if(b<B && !ins[a][B] && dfs(a,B))
{
dfsStack.push(Cmd(str_fill,'B','B'));
return true;
}
int ra=A-a;
int rb=B-b;
if(a>=rb)
{
if(!ins[a-rb][B] && dfs(a-rb,B))
{
dfsStack.push(Cmd(str_pour,'A','B'));
return true;
}
}
else
{
][a+b] && dfs(,a+b))
{
dfsStack.push(Cmd(str_pour,'A','B'));
return true;
}
}
if(b>=ra)
{
if(!ins[A][b-ra] && dfs(A,b-ra))
{
dfsStack.push(Cmd(str_pour,'B','A'));
return true;
}
}
else
{
] && dfs(a+b,))
{
dfsStack.push(Cmd(str_pour,'B','A'));
return true;
}
}
return false;
}
void output()
{
while(!dfsStack.empty())
{
dfsStack.top().output();
dfsStack.pop();
}
}
int main()
{
while(input())
{
init();
dfs(,);
output();
}
;
}
Problem:ZOJ P1005
P1025:贪心
#include <cstdio>
#include <cstring>
#include <algorithm>
;
int s[maxN];
int ans;
#include <utility>
typedef std::pair<int,int> Pr;
Pr st[maxN];
int N;
void input()
{
scanf("%d",&N);
;i<=N;i++)
scanf("%d%d",&st[i].first,&st[i].second);
}
int solve()
{
std::sort(st+,st+N+);
ans=;
;i<=N;i++)
{
bool ok=false;
;j<=ans && !ok;j++)
if(st[i].second>=s[j])
{
s[j]=st[i].second;
ok=true;
}
if(!ok)
s[++ans]=st[i].second;
}
return ans;
}
int main()
{
int cs; scanf("%d",&cs);
while(cs--)
{
input();
printf("%d\n",solve());
}
;
}
Problem:ZOJ P1025
P1074:裸的最大子矩阵
#include <cstdio>
#include <cstring>
#include <algorithm>
;
int v[maxN][maxN];
int p[maxN][maxN]; //prefix
int N;
void input()
{
scanf("%d",&N);
;i<=N;i++)
;j<=N;j++)
scanf("%d",v[i]+j);
}
void init()
{
;j<=N;j++)
{
p[][j]=;
p[][j]=v[][j];
;i<=N;i++)
p[i][j]=p[i-][j]+v[i][j];
}
}
int solve()
{
int ans=0x90000000;
;u<=N;u++)
for(int d=u;d<=N;d++)
{
;
;j<=N;j++)
{
opt=opt<?(p[d][j]-p[u-][j]):opt+(p[d][j]-p[u-][j]);
ans=std::max(ans,opt);
}
}
return ans;
}
int main()
{
input();
init();
printf("%d\n",solve());
;
}
Problem:ZOJ P1074
P1093:DAG最长路,DP或者SPFA都可以解决
(代码君已死)
P1107:记忆化搜索(直接DP比较难写)
#include <cstdio>
#include <cstring>
#include <algorithm>
;
int opt[maxN][maxN];
int val[maxN][maxN];
int N,K;
bool input()
{
scanf("%d%d",&N,&K);
) return false;
;i<N;i++)
;j<N;j++)
scanf("%d",val[i]+j);
return true;
}
void init()
{
memset(opt,,sizeof(opt));
}
int search(int hor,int ver)
{
if(opt[hor][ver]) return opt[hor][ver];
;u<=K && hor-u>=;u++)
if(val[hor-u][ver]>val[hor][ver])
opt[hor][ver]=std::max(opt[hor][ver],search(hor-u,ver));
;d<=K && hor+d<N;d++)
if(val[hor+d][ver]>val[hor][ver])
opt[hor][ver]=std::max(opt[hor][ver],search(hor+d,ver));
;l<=K && ver-l>=;l++)
if(val[hor][ver-l]>val[hor][ver])
opt[hor][ver]=std::max(opt[hor][ver],search(hor,ver-l));
;r<=K && ver+r<N;r++)
if(val[hor][ver+r]>val[hor][ver])
opt[hor][ver]=std::max(opt[hor][ver],search(hor,ver+r));
opt[hor][ver]+=val[hor][ver];
return opt[hor][ver];
}
int main()
{
while(input())
{
init();
printf(,));
}
;
}
Problem:ZOJ P1107
P1108:LIS
#include <cstdio>
#include <cstring>
#include <algorithm>
;
struct Mouse
{
int weight;
int speed;
int idx;
bool operator < (const Mouse& other) const
{
return this->weight > other.weight;
}
};
Mouse ms[maxN];
;
void input()
{
while(scanf("%d%d",&ms[N].weight,&ms[N].speed)!=EOF)
{ ms[N].idx=N; N++; }
N--;
}
int dp[maxN];
int last[maxN];
void init()
{
;i<=N;i++) dp[i]=;
;i<=N;i++) last[i]=i;
}
void solve()
{
init();
,mxn=;
std::sort(ms+,ms+N+);
;i<=N;i++)
;j<i;j++)
if(ms[j].weight>ms[i].weight && ms[j].speed<ms[i].speed)
{
>dp[i])
{
dp[i]=dp[j]+;
last[i]=j;
if(dp[i]>mx)
{
mx=dp[i];
mxn=i;
}
}
}
printf("%d\n",mx);
while(last[mxn]!=mxn)
{
printf("%d\n",ms[mxn].idx);
mxn=last[mxn];
}
printf("%d\n",ms[mxn].idx);
}
int main()
{
input();
solve();
;
}
Problem:ZOJ P1108
P1149:很裸的多重背包(一开始居然没发现,果然自己弱爆了……)
#include <cstdio>
#include <cstring>
#include <algorithm>
;
;
const char* success="Can be divided.";
const char* fail="Can't be divided.";
const char* tpl="Collection #%d:\n%s\n\n";
int dp[maxV];
int N;
int v[maxN];
void init()
{
memset(dp,,sizeof(dp));
N=;
}
];
;
bool proc()
{
;i<=;i++) scanf("%d",cnt+i);
bool end=true;
;i<=;i++) if(cnt[i]) { end=false; break; }
if(end) return false;
;
;i<=;i++) sum+=cnt[i]*i;
)
{
printf(tpl,++cs,fail);
return true;
}
sum>>=;
init();
;i<=;i++)
{
;
while(x<=cnt[i])
{
v[++N]=x*i;
cnt[i]-=x;
x<<=;
}
if(cnt[i]) v[++N]=cnt[i]*i;
}
;i<=N;i++)
for(int j=sum;j>=v[i];j--)
dp[j]=std::max(dp[j],dp[j-v[i]]+v[i]);
printf(tpl,++cs,dp[sum]==sum?success:fail);
return true;
}
int main()
{
while(proc());
;
}
Problem:ZOJ P1149
由于只需判定可行性,所以此题的dp数组可以用bool代替,初值为dp[0]=true
#include <cstdio>
#include <cstring>
#include <algorithm>
;
;
const char* success="Can be divided.";
const char* fail="Can't be divided.";
const char* tpl="Collection #%d:\n%s\n\n";
bool dp[maxV];
int N;
int v[maxN];
void init()
{
memset(dp,,sizeof(dp));
N=;
}
];
;
bool proc()
{
;i<=;i++) scanf("%d",cnt+i);
bool end=true;
;i<=;i++) if(cnt[i]) { end=false; break; }
if(end) return false;
;
;i<=;i++) sum+=cnt[i]*i;
)
{
printf(tpl,++cs,fail);
return true;
}
sum>>=;
init();
;i<=;i++)
{
;
while(x<=cnt[i])
{
v[++N]=x*i;
cnt[i]-=x;
x<<=;
}
if(cnt[i]) v[++N]=cnt[i]*i;
}
dp[]=true;
;i<=N;i++)
for(int j=sum;j>=v[i];j--)
dp[j]|=dp[j-v[i]];
printf(tpl,++cs,dp[sum]?success:fail);
return true;
}
int main()
{
while(proc());
;
}
Problem:ZOJ P1149(Optimized)
P1196:DP,dp[x][y]表示前x个餐馆处设置第y个depot,其之前部分的最小代价。代码中使用滚动数组压缩掉了第2维
#include <cstdio>
#include <cstring>
#include <algorithm>
;
;
const int inf=0x3f3f3f3f;
int dp[maxN];
int dist[maxN];
int N,K;
bool input()
{
scanf("%d%d",&N,&K);
if(!N) return false;
;i<=N;i++) scanf("%d",dist+i);
dist[N+]=inf;
dist[]=-inf;
return true;
}
int gap[maxN][maxN];
void initGap()
{
memset(gap,,sizeof(gap));
;i<N;i++)
;j<=N+;j++)
;k<j;k++)
gap[i][j]+=std::min(dist[j]-dist[k],dist[k]-dist[i]);
}
int solve()
{
memset(dp,0x3f,sizeof(dp));
for(int i=N;i;i--)
dp[i]=gap[][i];
;t<=K;t++)
{
for(int i=N;i>=t;i--)
;j>=;j--)
dp[i]=std::min(dp[i],dp[j]+gap[j][i]);
}
int ans=inf;
for(int i=K;i<=N;i++)
ans=std::min(ans,dp[i]+gap[i][N+]);
return ans;
}
;
int main()
{
while(input())
{
initGap();
printf("Chain %d\nTotal distance sum = %d\n\n",++cs,solve());
}
;
}
Problem:ZOJ P1196
P1440:置换数+逆序对
如果代码中加一句#undef TEST,我们实际上就对val进行了离散化(比一般的排序+lower_bound要高效一些)
此外需要注意一下数据范围,逆序对数可能爆int
#include <cstdio>
#include <cstring>
#include <algorithm>
;
int val[maxN];
int pos[maxN];
bool vis[maxN];
int N;
void input()
{
scanf("%d",&N);
;i<=N;i++)
{
scanf("%d",val+i);
pos[i]=i;
}
}
inline bool cmp(int x,int y)
{
return val[x] < val[y];
}
inline void swap(int* x,int* y)
{
int t=*x; *x=*y; *y=t;
}
#define TEST
int getMinSwapCnt()
{
std::sort(pos+,pos+N+,cmp);
memset(vis,,sizeof(vis));
#ifndef TEST
;i<=N;i++) val[pos[i]]=i;
#endif
;
;i<=N;i++)
if(!vis[i])
{
#ifndef TEST
for(int j=i;!vis[j];j=val[j]) vis[j]=true;
#else
for(int j=i;!vis[j];j=pos[j]) vis[j]=true;
#endif
++res;
}
return N-res;
}
typedef long long int64;
int64 mergeSort_aux(int left,int right)
{
;
==right)
{
;
; }
}
;
int64 res=mergeSort_aux(left,mid)+mergeSort_aux(mid+,right);
;
int p=left;
while(i<=mid && j<=right)
{
if(val[i]<val[j]) pos[p++]=val[i++];
else
{
pos[p++]=val[j++];
res+=(mid+-i);
}
}
for(;i<=mid;i++) pos[p++]=val[i];
for(;j<=right;j++) pos[p++]=val[j];
memcpy(val+left,pos+left,(right-left+)*sizeof(int));
return res;
}
int64 getInvPairCnt()
{
,N);
}
#include <iostream>
int main()
{
input();
std::cout<<getMinSwapCnt()<<"\n";
std::cout<<getInvPairCnt()<<"\n";
;
}
Problem:ZOJ P1440
P1985:单调栈
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
;
int h[maxN];
int l[maxN],r[maxN];
int s[maxN],p;
int N;
bool input()
{
scanf("%d",&N);
if(!N) return false;
;i<N;i++) scanf("%d",h+i);
return true;
}
typedef long long int64;
int64 solve()
{
p=-;
;i<N;i++)
{
&& h[s[p]]>=h[i];p--);
l[i]=(p==-)?:s[p]+;
s[++p]=i;
}
p=-;
;i--)
{
&& h[s[p]]>=h[i];p--);
r[i]=(p==-)?N:s[p];
s[++p]=i;
}
int64 ans();
;i<N;i++)
ans=std::max(ans,int64(h[i])*(r[i]-l[i]));
return ans;
}
int main()
{
while(input()) std::cout<<solve()<<"\n";
;
}
Problem:ZOJ P1985
P2112:树套树或者平方分割均可
详见:http://www.cnblogs.com/Onlynagesha/p/5355133.html
template <class T>
struct SbtNode
{
typedef SbtNode<T> Node;
Node* lch;
Node* rch;
T val;
int lSize;
int rSize;
SbtNode(const T& _val):
lch(),rch(),val(_val),lSize(),rSize() {}
void assign(const T& _val)
{
lch=rch=;
val=_val;
lSize=rSize=;
}
};
template <class T,class Comp>
struct SizeBlcTree
{
,Left=,Right= };
typedef SbtNode<T> Node;
typedef SizeBlcTree<T,Comp> Sbt;
Node* root;
Comp cmp;
SizeBlcTree():root() {}
~SizeBlcTree() { clear(); }
void clear_aux(Node* _cur)
{
if(_cur->lch) clear_aux(_cur->lch);
if(_cur->rch) clear_aux(_cur->rch);
delete _cur;
}
void clear()
{
if(root) clear_aux(root);
root=;
}
Node* lRotate(Node* _cur)
{
Node* next=_cur->rch;
_cur->rch=next->lch;
next->lch=_cur;
_cur->rSize=next->lSize;
next->lSize+=(_cur->lSize+);
return next;
}
Node* rRotate(Node* _cur)
{
Node* next=_cur->lch;
_cur->lch=next->rch;
next->rch=_cur;
_cur->lSize=next->rSize;
next->rSize+=(_cur->rSize+);
return next;
}
Node* insert_aux(const T& _val,Node* _cur)
{
if(!_cur) return new Node(_val);
if(cmp(_val,_cur->val))
{
++_cur->lSize;
_cur->lch=insert_aux(_val,_cur->lch);
if(_cur->lch->lSize > _cur->rSize) return rRotate(_cur);
else if(_cur->lch->rSize > _cur->rSize)
{
_cur->lch=lRotate(_cur->lch);
return rRotate(_cur);
}
else return _cur;
}
else
{
++_cur->rSize;
_cur->rch=insert_aux(_val,_cur->rch);
if(_cur->rch->rSize > _cur->lSize) return lRotate(_cur);
else if(_cur->rch->lSize > _cur->lSize)
{
_cur->rch=rRotate(_cur->rch);
return lRotate(_cur);
}
else return _cur;
}
}
Sbt& operator << (const T& _val)
{
root=insert_aux(_val,root);
return *this;
}
Node* erase_aux(const T& _val,Node* _cur,bool& _found)
{
if(!_cur)
{
_found=false;
;
}
if(cmp(_val,_cur->val))
{
_cur->lch=erase_aux(_val,_cur->lch,_found);
if(_found) --_cur->lSize;
return _cur;
}
if(cmp(_cur->val,_val))
{
_cur->rch=erase_aux(_val,_cur->rch,_found);
if(_found) --_cur->rSize;
return _cur;
}
_found=true;
;
;
;
Node* res;
Node* &prev=res;
switch(status)
{
:
delete _cur;
;
:
res=_cur->lch;
delete _cur;
return res;
:
res=_cur->rch;
delete _cur;
return res;
:
prev=_cur;
if(prev->rch->lch)
{
--prev->rSize;
prev=prev->rch;
while(prev->lch->lch)
{
--prev->lSize;
prev=prev->lch;
}
_cur->val=prev->lch->val;
prev->lch=erase_aux(prev->lch->val,prev->lch,_found);
--prev->lSize;
}
else
{
_cur->val=_cur->rch->val;
_cur->rch=erase_aux(_cur->rch->val,_cur->rch,_found);
--_cur->rSize;
}
return _cur;
}
}
Sbt& operator >> (const T& _val)
{
bool found=false;
root=erase_aux(_val,root,found);
return *this;
}
int notMoreCount(const T& _val)
{
Node* cur=root;
;
while(cur)
{
if(cmp(_val,cur->val)) cur=cur->lch;
else
{
res+=(cur->lSize+);
cur=cur->rch;
}
}
return res;
}
int lessCount(const T& _val)
{
Node* cur=root;
;
while(cur)
{
if(cmp(cur->val,_val))
{
res+=(cur->lSize+);
cur=cur->rch;
}
else cur=cur->lch;
}
return res;
}
};
;
;
;
;
#include <functional>
#include <algorithm>
int unOrd[bktCount*bktSize];
using std::less;
SizeBlcTree<int,less<int> > all;
SizeBlcTree<int,less<int> > bucket[bktCount];
int N,K;
int cs;
#include <cstdio>
void init()
{
scanf("%d%d",&N,&K);
;i<N;i++)
{
scanf("%d",unOrd+i);
all<<unOrd[i];
bucket[i>>bktDigit] << unOrd[i];
}
}
inline void enumerate(int _rL,int _rR,int _val,int& _less,int& _notMore)
{
for(int i=_rL;i<=_rR;i++) if(unOrd[i]<=_val)
{
_notMore++;
if(unOrd[i]<_val) _less++;
}
}
int getAns(int _rL,int _rR,int _k)
{
int bktL = _rL>>bktDigit;
int bktR = _rR>>bktDigit;
int prevVal;
SbtNode<int> *cur=all.root;
while(cur)
{
;
;
if(bktL==bktR) enumerate(_rL,_rR,cur->val,less,notMore);
else
{
;i<bktR;i++)
{
notMore += bucket[i].notMoreCount(cur->val);
less += bucket[i].lessCount(cur->val);
}
enumerate(_rL,((bktL+)<<bktDigit)-,cur->val,less,notMore);
enumerate(bktR<<bktDigit,_rR,cur->val,less,notMore);
}
if(less<_k && notMore>=_k) return cur->val;
prevVal=cur->val;
if(less>=_k) cur=cur->lch;
else cur=cur->rch;
}
return prevVal;
}
void solve()
{
char cmd;
do cmd=getchar(); while(cmd==' ' || cmd=='\n');
if(cmd=='Q')
{
int rL,rR,k;
scanf("%d%d%d",&rL,&rR,&k);
printf(,rR-,k));
}
else
{
int pos,v;
scanf("%d%d",&pos,&v);
--pos;
all<<v;
bucket[pos>>bktDigit] >> unOrd[pos];
bucket[pos>>bktDigit] << (unOrd[pos]=v) ;
}
}
void reset()
{
all.clear();
int used=N>>bktDigit;
;i<=used;i++) bucket[i].clear();
}
int main()
{
scanf("%d",&cs);
while(cs--)
{
init();
while(K--) solve();
reset();
}
;
}
Problem:ZOJ P2112
P2114:LCTdf好!!!
人生第一棵Link-cut-tree
#include <cstdio>
#include <cstring>
#include <algorithm>
,Right= };
struct SplayNode;
SplayNode* vir;
struct SplayNode
{
int dist;
int totDist;
bool isRoot;
SplayNode* parent;
SplayNode* child[];
void init()
{
dist=totDist=;
isRoot=true;
parent=child[]=child[]=vir;
}
void clear()
{
if(child[Left]!=vir) child[Left]->clear();
if(child[Right]!=vir) child[Right]->clear();
delete this;
}
void update()
{
this->totDist =
child[Left]->totDist+child[Right]->totDist+this->dist;
}
void rotate(int dir)
//If dir==Right then rotate clockwise, else rotate counter-clockwise
{
if(parent==parent->parent->child[Left])
parent->parent->child[Left]=this;
else if(parent==parent->parent->child[Right])
parent->parent->child[Right]=this;
parent->child[dir^]=this->child[dir];
child[dir]->parent=this->parent;
child[dir]=parent;
parent=parent->parent;
child[dir]->parent=this;
}
void zigzig(int dir)
{
parent->rotate(dir);
this->rotate(dir);
child[dir]->child[dir]->update();
child[dir]->update();
this->update();
}
void zigzag(int dir) //dir depends on first rotation
{
rotate(dir);
rotate(dir^);
child[Left]->update();
child[Right]->update();
this->update();
}
void zig(int dir)
{
rotate(dir);
child[dir]->update();
this->update();
}
void splay()
{
while(!isRoot)
{
;
;
;
if(!parent->isRoot)
{
if(parent->parent->isRoot) this->isRoot=true;
;
;
}
else
this->isRoot=true;
switch(status)
{
: zig(Right);
child[Right]->isRoot=false;
break;
: zig(Left);
child[Left]->isRoot=false;
break;
: zigzig(Right);
if(isRoot) child[Right]->child[Right]->isRoot=false;
break;
: zigzag(Left);
if(isRoot) child[Right]->isRoot=false;
break;
: zigzag(Right);
if(isRoot) child[Left]->isRoot=false;
break;
:zigzig(Left);
if(isRoot) child[Left]->child[Left]->isRoot=false;
break;
default:break;
}
}
}
};
int access(SplayNode* u)
{
SplayNode* v=vir;
;
while(u!=vir)
{
u->splay();
u->child[Right]->isRoot=true;
res=u->child[Right]->totDist;
u->child[Right]=v;
v->isRoot=false;
u->update();
v=u; u=u->parent;
}
return res + v->child[Right]->totDist;
}
inline int query(SplayNode* u,SplayNode* v)
{
access(u);
return access(v);
}
void initVir()
{
vir=new SplayNode;
vir->init();
}
;
SplayNode node[maxN];
int center[maxN];
int N,Q;
;
inline void link(int u,int v,int len)
{
access(node+u);
node[u].splay();
center[u]=v;
node[u].parent=node+v;
node[u].dist=len;
node[u].update();
}
inline void initNode()
{
;i<=N;i++) node[i].init();
;i<=N;i++) center[i]=i;
}
int getCenter(int x)
{
return center[x]==x ? x :
center[x]=getCenter(center[x]);
}
#define DEBUG
#undef DEBUG
#ifdef DEBUG
;
#endif
void solve()
{
lastRes=;
scanf("%d%d",&N,&Q);
initNode();
char cmd;
int v1,v2,len;
while(Q--)
{
do cmd=getchar(); while(cmd==' ' || cmd=='\n');
if(cmd=='Q')
{
scanf("%d%d",&v1,&v2);
if(getCenter(v1)==getCenter(v2))
printf("%d\n",lastRes=query(node+v1,node+v2));
else printf("Not connected.\n");
#ifdef DEBUG
printf("#%d query successful.\n",++qc);
#endif
}
else
{
scanf("%d%d%d",&v1,&v2,&len);
#ifndef DEBUG
v1=(v1-lastRes-)%N;
) v1+=N;
v2=(v2-lastRes-)%N;
) v2+=N;
#endif
link(getCenter(v1),getCenter(v2),len);
}
}
}
int main()
{
//freopen("/home/onlynagesha/Desktop/a.in","r",stdin);
//freopen("t.out","w",stdout);
initVir();
int X; scanf("%d",&X);
while(X--) solve();
;
}
Problem:ZOJ P2114
P2334:左偏树+并查集
详见:http://www.cnblogs.com/Onlynagesha/p/5406403.html
#include <cstdio>
#include <cstring>
#include <algorithm>
template <class T>
struct HeapNode
{
typedef HeapNode<T> Node;
Node* lch;
Node* rch;
T val;
int dist;
HeapNode(),rch(),val(_val),dist() {}
void clear()
{
if(lch) lch->clear();
if(rch) rch->clear();
delete this;
}
};
template <class T,class Comp>
struct LeftistHeap
{
typedef HeapNode<T> Node;
typedef LeftistHeap<T,Comp> Heap;
Node* root;
Comp cmp;
LeftistHeap():root() {}
~LeftistHeap()
{
clear();
}
void clear()
{
if(root) root->clear();
root=;
}
Node* merge(Node* A,Node* B)
{
if(!A) return B;
if(!B) return A;
if(cmp(B->val,A->val)) std::swap(A,B);
A->rch=merge(B,A->rch);
if(!A->lch || A->rch->dist > A->lch->dist)
std::swap(A->lch,A->rch);
A->dist = (A->rch) ? A->rch->dist + : ;
return A;
}
void push(const T& _val)
{
Node* nNode=new Node(_val);
root=merge(root,nNode);
}
Heap& operator << (const T& _val)
{
push(_val);
return *this;
}
T top()
{
return root->val;
}
void pop()
{
Node* temp=root;
root=merge(temp->lch,temp->rch);
delete temp;
}
Heap& operator >> (T& _dest)
{
_dest=top();
pop();
return *this;
}
void merge(Heap& _other)
{
this->root=merge(this->root,_other.root);
_other.root=;
}
bool empty()
{
;
}
};
#include <functional>
;
int N,M;
int idx[maxN];
int father(int x)
{
return idx[x]==x ? x : idx[x]=father(idx[x]) ;
}
LeftistHeap<int,std::greater<int> > heap[maxN];
void init()
{
;i<maxN;i++) heap[i].clear();
;i<maxN;i++) idx[i]=i;
}
bool solve()
{
init();
if(scanf("%d",&N)==EOF) return false;
;i<=N;i++)
{
int s; scanf("%d",&s);
heap[i].push(s);
}
scanf("%d\n",&M);
while(M--)
{
int mk1,mk2;
scanf("%d%d",&mk1,&mk2);
int f1=father(mk1);
int f2=father(mk2);
if(f1==f2)
{
printf("-1\n");
continue;
}
int s1,s2;
heap[f1]>>s1;
heap[f2]>>s2;
if(f1<f2)
{
idx[f2]=f1;
heap[f1].merge(heap[f2]);
);
));
heap[f1] << (s1>>) << (s2>>);
}
else
{
idx[f1]=f2;
heap[f2].merge(heap[f1]);
);
));
heap[f2] << (s1>>) << (s2>>);
}
}
return true;
}
int main()
{
while(solve());
;
}
Problem:ZOJ P2334
P2592:有一个非常神奇的性质
#include <cstdio>
int main()
{
int N,T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&N);
;
;i<N;i++)
{
int v;
scanf("%d",&v);
tot+=v;
}
printf(?tot:);
}
;
}
Problem:ZOJ P2592
然而偶的思路就有些繁琐了,而且套了个SBT模板(参考:http://www.cnblogs.com/Onlynagesha/p/5350398.html)
基本思想是维护前缀和序列,在序列“移动”过程中设立了一个offset变量,相当于给整棵树打了一个LazyTag
类似的思想可用于NOI2005“郁闷的出纳员”一题
template <class T>
struct SbtNode
{
typedef SbtNode<T> Node;
Node* lch;
Node* rch;
T val;
int lSize;
int rSize;
SbtNode(const T& _val):
lch(),rch(),val(_val),lSize(),rSize() {}
void assign(const T& _val)
{
lch=rch=;
val=_val;
lSize=rSize=;
}
};
template <class T,class Comp>
struct SizeBlcTree
{
,Left=,Right= };
typedef SbtNode<T> Node;
typedef SizeBlcTree<T,Comp> Sbt;
Node* root;
Comp cmp;
SizeBlcTree():root() {}
~SizeBlcTree() { clear(); }
void clear_aux(Node* _cur)
{
if(_cur->lch) clear_aux(_cur->lch);
if(_cur->rch) clear_aux(_cur->rch);
delete _cur;
}
void clear()
{
if(root) clear_aux(root);
root=;
}
Node* lRotate(Node* _cur)
{
Node* next=_cur->rch;
_cur->rch=next->lch;
next->lch=_cur;
_cur->rSize=next->lSize;
next->lSize+=(_cur->lSize+);
return next;
}
Node* rRotate(Node* _cur)
{
Node* next=_cur->lch;
_cur->lch=next->rch;
next->rch=_cur;
_cur->lSize=next->rSize;
next->rSize+=(_cur->rSize+);
return next;
}
Node* insert_aux(const T& _val,Node* _cur)
{
if(!_cur) return new Node(_val);
if(cmp(_val,_cur->val))
{
++_cur->lSize;
_cur->lch=insert_aux(_val,_cur->lch);
if(_cur->lch->lSize > _cur->rSize) return rRotate(_cur);
else if(_cur->lch->rSize > _cur->rSize)
{
_cur->lch=lRotate(_cur->lch);
return rRotate(_cur);
}
else return _cur;
}
else
{
++_cur->rSize;
_cur->rch=insert_aux(_val,_cur->rch);
if(_cur->rch->rSize > _cur->lSize) return lRotate(_cur);
else if(_cur->rch->lSize > _cur->lSize)
{
_cur->rch=rRotate(_cur->rch);
return lRotate(_cur);
}
else return _cur;
}
}
Sbt& operator << (const T& _val)
{
root=insert_aux(_val,root);
return *this;
}
Node* erase_aux(const T& _val,Node* _cur,bool& _found)
{
if(!_cur)
{
_found=false;
;
}
if(cmp(_val,_cur->val))
{
_cur->lch=erase_aux(_val,_cur->lch,_found);
if(_found) --_cur->lSize;
return _cur;
}
if(cmp(_cur->val,_val))
{
_cur->rch=erase_aux(_val,_cur->rch,_found);
if(_found) --_cur->rSize;
return _cur;
}
_found=true;
;
;
;
Node* res;
Node* &prev=res;
switch(status)
{
:
delete _cur;
;
:
res=_cur->lch;
delete _cur;
return res;
:
res=_cur->rch;
delete _cur;
return res;
:
prev=_cur;
if(prev->rch->lch)
{
--prev->rSize;
prev=prev->rch;
while(prev->lch->lch)
{
--prev->lSize;
prev=prev->lch;
}
_cur->val=prev->lch->val;
prev->lch=erase_aux(prev->lch->val,prev->lch,_found);
--prev->lSize;
}
else
{
_cur->val=_cur->rch->val;
_cur->rch=erase_aux(_cur->rch->val,_cur->rch,_found);
--_cur->rSize;
}
return _cur;
}
}
Sbt& operator >> (const T& _val)
{
bool found=false;
root=erase_aux(_val,root,found);
return *this;
}
T min()
{
Node* cur=root;
while(cur->lch) cur=cur->lch;
return cur->val;
}
};
;
int T,N;
int offset;
int arr[maxN];
int prefix[maxN];
#include <functional>
#include <cstdio>
#include <cstring>
#include <algorithm>
SizeBlcTree<int,std::less<int> > sbt;
void init()
{
offset=;
prefix[]=;
sbt.clear();
}
int solve()
{
init();
scanf("%d",&N);
;i<=N;i++)
{
scanf("%d",arr+i);
prefix[i]=prefix[i-]+arr[i];
sbt<<prefix[i];
}
? : ;
prefix[]=prefix[N];
;i<N;i++)
{
offset-=arr[i];
sbt>>prefix[i];
prefix[i]=prefix[i-]+arr[i];
sbt<<prefix[i];
) ++ans;
}
return ans;
}
int main()
{
scanf("%d",&T);
while(T--) printf("%d\n",solve());
;
}
Another Solution to ZOJ P2592
P2652:只需分两种情况:改变第一行或不改变第一行。此后所有的状态都可以推导出来,无需再进行枚举
#include <cstdio>
#include <cstring>
#include <algorithm>
;
;
int mat[maxN][maxN];
int N,M;
bool input()
{
if(scanf("%d%d",&M,&N)==EOF) return false;
;i<=M;i++)
;j<=N;j++)
scanf("%d",mat[i]+j);
return true;
}
bool ch[maxN];
int check()
{
;
memset(ch,,sizeof(ch));
;i<=N;i++)
][i]<) { ch[i]=true; ++res; }
;i<=N;i++)
;j<=M;j++)
mat[j][i]=-mat[j][i];
;j<=M;j++)
{
;;
;i<=N;i++)
) ++c;
if(c==N) ++res;
else if(c) { res=inf; break; }
}
;i<=N;i++)
;j<=M;j++)
mat[j][i]=-mat[j][i];
return res;
}
int solve()
{
int ans=check();
;i<=N;i++) mat[][i]=-mat[][i];
ans=std::min(ans,+check());
:ans;
}
int main()
{
while(input())
printf("%d\n",solve());
;
}
Problem:ZOJ P2652
P2671:线段树
#include <cstdio>
#include <cstring>
#include <algorithm>
;
int N,M,R;
);
struct Mat
{
][];
Mat() { memset(v,,sizeof(v)); }
Mat operator * (const Mat& u) const
{
Mat a;
;i<;i++)
;j<;j++)
{
;k<;k++)
a.v[i][j]+=this->v[i][k]*u.v[k][j];
a.v[i][j]%=R;
}
return a;
}
void read()
{
scanf(],v[]+,v[],v[]+);
}
void print()
{
) printf("\n");
printf(][],v[][],v[][],v[][]);
}
};
Mat mt[maxN];
struct SegTree
{
Mat* node;
int size;
SegTree(*size+]; }
~SegTree() { delete[] node; }
template <class RAIter>
void init_aux(RAIter begin,int len,int cur)
{
) {
node[cur]=*begin; return;
}
);
init_aux(begin,len>>,cur+);
init_aux(begin+(len>>),(len+)>>,rt);
node[cur]=node[cur+]*node[rt];
}
template <class RAIter>
void init(RAIter begin)
{
init_aux(begin,size,);
}
Mat ask_aux(int rl,int rr,int nl,int nr,int cur)
{
if(rl<=nl && rr>=nr) return node[cur];
;
);
);
else if(rl>=mid) return ask_aux(rl,rr,mid,nr,rt);
)*ask_aux(rl,rr,mid,nr,rt);
}
Mat ask(int l,int r)
{
,size,);
}
};
bool input()
{
if(scanf("%d%d%d",&R,&N,&M)==EOF) return false;
;i<=N;i++)
mt[i].read();
return true;
}
void proc()
{
SegTree tree(N);
tree.init(mt+);
int l,r;
Mat ans;
while(M--)
{
scanf("%d%d",&l,&r);
ans=tree.ask(l-,r);
ans.print();
}
}
int main()
{
);
while(input())
proc();
;
}
Problem:ZOJ P2671
P2688:很有意思的题目,题解参考:http://blog.csdn.net/axuan_k/article/details/47447281
#include <cstdio>
#include <cstring>
#include <algorithm>
;
;
double v[maxK][maxN];
int N;
bool input()
{
scanf("%d",&N);
if(!N) return false;
];
;f<=N;f++)
{
;i<;i++)
scanf("%lf",a+i);
;b<;b++)
{
v[b][f]=0.0;
,j=b;i<;i++,j>>=)
{
) v[b][f]+=a[i];
else v[b][f]-=a[i];
}
}
}
return true;
}
double solve()
{
double mx,mn;
double ans(-1e100);
;b<;b++)
{
mx=-1e100; mn=1e100;
;i<=N;i++)
{
mx=std::max(mx,v[b][i]);
mn=std::min(mn,v[b][i]);
}
ans=std::max(ans,mx-mn);
}
return ans;
}
int main()
{
while(input())
printf("%.2lf\n",solve());
;
}
Problem:ZOJ P2688
P3164:背包问题的加强版,输入及其恶心,代码也很丑……(/= _ =)/~┴┴
#include <cstdio>
#include <cstring>
#include <algorithm>
;
int N,D;
int K[maxN],E[maxN],P[maxN];
int G;
int inGrp[maxN];
char buf[maxN];
void procGrp(int idx)
{
;
;;i++)
{
if(buf[i]=='\n' || buf[i]=='\0')
{
if(v) inGrp[v]=idx;
break;
}
else if(buf[i]==' ')
{ inGrp[v]=idx; v=; }
else
{ v*=; v+=(buf[i]-'); }
}
}
bool input()
{
if(scanf("%d%d",&N,&D)==EOF)
return false;
;i<=N;i++)
{
scanf("%d%d%d",K+i,E+i,P+i);
if(!K[i]) K[i]=D/P[i];
}
scanf("%d",&G);
memset(inGrp,-,sizeof(inGrp));
fgets(buf,maxN,stdin);
;i<G;i++)
{
fgets(buf,maxN,stdin);
procGrp(i);
}
return true;
}
][maxN];
int dp[maxN];
int solve()
{
memset(grpOpt,0xc0,sizeof(grpOpt));
;i<;i++) grpOpt[i][]=;
memset(dp,]=;
;i<=N;i++)
)
{
int& grp=inGrp[i];
;j<=K[i] && j*P[i]<=D;j++)
grpOpt[grp][j*P[i]]=std::max
(grpOpt[grp][j*P[i]],j*E[i]);
}
;i<=N;i++)
)
{
int k=K[i];
;j<=k;j<<=)
{
k-=j;
for(int v=D;v>=P[i]*j;v--)
dp[v]=std::max(dp[v],dp[v-P[i]*j]+E[i]*j);
}
if(k) for(int v=D;v>=P[i]*k;v--)
dp[v]=std::max(dp[v],dp[v-P[i]*k]+E[i]*k);
}
;i<G;i++)
for(int v=D;v;v--)
for(int w=v;w;w--)
dp[v]=std::max(dp[v],dp[v-w]+grpOpt[i][w]);
return dp[D];
}
int main()
{
while(input())
{
int ans=solve();
) printf("i'm sorry...\n");
else printf("%d\n",ans);
}
;
}
Problem:ZOJ P3164
P3195:LCA
预处理每个点到根节点的距离dist
记三个点为v1,v2,v3,两两配对的LCA分别为u1,u2,u3,那么ans=dist(v1)+dist(v2)+dist(v3)-dist(u1)-dist(u2)-dist(u3)
毫不夸张的说这是我写过的最恶心的代码( ̄﹏ ̄)
map和多余的qv*数组都可以省下
1 #include <cstdio>
2 #include <cstring>
3 #include <algorithm>
4 #include <utility>
5 #include <map>
6
7 typedef std::pair<int,int> Pr;
8
9 std::map <Pr,int> lca;
10
11 const int maxQ=420005;
12 const int maxN=50005;
13 const int __maxN=70005;
14
15 Pr query[maxQ]; // first=to // second=next
16 int qHead[maxN];
17 int qCnt;
18
19 struct Edge
20 {
21 int to;
22 int weight;
23 int next;
24
25 void assign(int t,int w,int n)
26 {
27 to=t; weight=w; next=n;
28 }
29 };
30
31 Edge edge[maxN*2];
32 int eHead[maxN];
33 int eCnt;
34
35 void initL()
36 {
37 lca.clear();
38 qCnt = eCnt = 0;
39 memset(eHead,-1,sizeof(eHead));
40 memset(qHead,-1,sizeof(qHead));
41 }
42
43 inline void addEdge(int v1,int v2,int w)
44 {
45 edge[eCnt].assign(v2,w,eHead[v1]);
46 eHead[v1]=eCnt++;
47 edge[eCnt].assign(v1,w,eHead[v2]);
48 eHead[v2]=eCnt++;
49 }
50
51 inline void addQuery(int v1,int v2)
52 {
53 query[qCnt].first=v2;
54 query[qCnt].second=qHead[v1];
55 qHead[v1]=qCnt++;
56 query[qCnt].first=v1;
57 query[qCnt].second=qHead[v2];
58 qHead[v2]=qCnt++;
59 }
60
61 int N,Q;
62 int qv1[__maxN],qv2[__maxN],qv3[__maxN];
63
64 bool input()
65 {
66 if(scanf("%d",&N)==EOF) return false;
67 initL();
68 int v1,v2,w;
69 for(int i=1;i<N;i++)
70 {
71 scanf("%d%d%d",&v1,&v2,&w);
72 addEdge(v1,v2,w);
73 }
74 scanf("%d",&Q);
75 for(int i=1;i<=Q;i++)
76 {
77 scanf("%d%d%d",qv1+i,qv2+i,qv3+i);
78 addQuery(qv1[i],qv2[i]);
79 addQuery(qv2[i],qv3[i]);
80 addQuery(qv1[i],qv3[i]);
81 }
82 return true;
83 }
84
85 bool vis[maxN];
86 int dist[maxN];
87
88 void initV()
89 {
90 memset(vis,0,sizeof(vis));
91 }
92
93 void build(int cur,int len)
94 {
95 vis[cur]=true;
96 dist[cur]=len;
97 for(int e=eHead[cur];e>-1;e=edge[e].next)
98 if(!vis[edge[e].to])
99 build(edge[e].to,len+edge[e].weight);
100 }
101
102 int setn[maxN];
103
104 void initS()
105 {
106 for(int i=1;i<=N;i++) setn[i]=i;
107 memset(vis,0,sizeof(vis));
108 }
109
110 int find(int x) { return setn[x]==x?x:setn[x]=find(setn[x]); }
111
112 void dfs(int cur)
113 {
114 vis[cur]=true;
115 for(int e=eHead[cur];e>-1;e=edge[e].next)
116 if(!vis[edge[e].to])
117 {
118 dfs(edge[e].to);
119 setn[edge[e].to]=cur;
120 }
121 for(int q=qHead[cur];q>-1;q=query[q].second)
122 if(vis[query[q].first])
123 {
124 int anc=setn[find(query[q].first)];
125 lca[Pr(cur,query[q].first)]=anc;
126 lca[Pr(query[q].first,cur)]=anc;
127 }
128 }
129
130 void solve_aux()
131 {
132 for(int i=1;i<=Q;i++)
133 {
134 int lca1=lca[Pr(qv1[i],qv2[i])];
135 int lca2=lca[Pr(qv2[i],qv3[i])];
136 int lca3=lca[Pr(qv1[i],qv3[i])];
137 printf("%d\n",dist[qv1[i]]+dist[qv2[i]]+dist[qv3[i]]-
138 dist[lca1]-dist[lca2]-dist[lca3]);
139 }
140 }
141
142 int flag=0;
143 void solve()
144 {
145 if(flag++) printf("\n");
146 initV();
147 build(0,0);
148 initS();
149 dfs(0);
150 solve_aux();
151 }
152
153 int main()
154 {
155 while(input()) solve();
156 return 0;
157 }
A Very Nasty Solution to ZOJ P3195
P3197:区间覆盖问题,贪心思想很简单,但是代码并不好写(´・ω・`)
最后参(chao)考(xi)了这位的代码才AC掉:http://blog.csdn.net/zhangwenjun32/article/details/4149683
此题很重要
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <utility>
typedef std::pair<int,int> Pr;
;
Pr rg[maxN];
int N;
void input()
{
scanf("%d",&N);
;i<=N;i++)
scanf("%d%d",&rg[i].first,&rg[i].second);
}
int solve()
{
std::sort(rg+,rg+N+);
),end();
);
);
while(end<N)
{
int tp=-maxN;
begin=end+;
for(;cur<=N && rg[cur].first<=begin;cur++)
tp=std::max(tp,rg[cur].second);
++ans; end=tp;
}
return ans;
}
int main()
{
int T; scanf("%d",&T);
while(T--)
{
input();
printf("%d\n",solve());
}
;
}
Problem:ZOJ P3197
P3201:树形DP
因为很久没写树形DP了所以卡了很久……
#include <cstdio>
#include <cstring>
#include <algorithm>
int N,M;
;
int lch[maxN];
int rch[maxN];
int adjList[maxN][maxN];
int head[maxN];
bool vis[maxN];
int dpQueue[maxN];
int dp[maxN][maxN];
int dpa[maxN][maxN];
int qp;
int val[maxN];
void init()
{
memset(lch,-,sizeof(lch));
memset(rch,-,sizeof(rch));
memset(head,,sizeof(head));
memset(vis,,sizeof(vis));
;i<maxN;i++) dp[i][]=dpa[i][]=;
qp=;
}
bool input()
{
if(scanf("%d%d",&N,&M)==EOF) return false;
init();
;i<=N;i++) scanf("%d",val+i);
int v1,v2;
;i<N;i++)
{
scanf("%d%d",&v1,&v2);
++v1; ++v2;
adjList[v1][head[v1]++]=v2;
adjList[v2][head[v2]++]=v1;
}
return true;
}
void build(int cur)
{
vis[cur]=true;
int next,i;
int last;
;i<head[cur];i++)
{
next=adjList[cur][i];
if(!vis[next])
{
last=lch[cur]=next;
build(next);
break;
}
}
if(i==head[cur]) return;
for(;i<head[cur];i++)
{
next=adjList[cur][i];
if(!vis[next])
{
build(next);
last=rch[last]=next;
}
}
}
void dfs(int cur)
{
) dfs(rch[cur]);
) dfs(lch[cur]);
dpQueue[qp++]=cur;
}
const int minf=0xf0000000;
int solve_aux()
{
int ans=minf;
;i<qp;i++)
{
;
int cur=dpQueue[i];
) status|=;
) status|=;
int lc,rc;
switch(status)
{
:
dp[cur][]=dpa[cur][]=val[cur];
;j<=M;j++) dp[cur][j]=dpa[cur][j]=minf;
break;
:
rc=rch[cur];
dp[cur][]=val[cur];
;j<=M;j++) dp[cur][j]=minf;
;j<=M;j++)
dpa[cur][j]=std::max(dpa[rc][j],dpa[rc][j-]+val[cur]);
break;
:
lc=lch[cur];
;j<=M;j++)
dp[cur][j]=dpa[cur][j]=dpa[lc][j-]+val[cur];
break;
:
lc=lch[cur]; rc=rch[cur];
;j<=M;j++)
dp[cur][j]=dpa[lc][j-]+val[cur];
;j<=M;j++)
{
dpa[cur][j]=minf;
;k<=j;k++)
dpa[cur][j]=std::max(dpa[cur][j],dpa[rc][j-k]+dp[cur][k]);
}
break;
}
ans=std::max(ans,dp[cur][M]);
}
return ans;
}
int solve()
{
build();
dfs();
return solve_aux();
}
int main()
{
while(input()) printf("%d\n",solve());
;
}
Problem:ZOJ P3201
P3224:分段讨论
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
typedef long long Lint;
;
;
using std::cin;
using std::cout;
Lint ex[maxN][maxL];
int N;
Lint A,B;
Lint v[maxN];
Lint r[maxN*maxL];
int cnt;
bool input()
{
if(!(cin>>N)) return false;
cin>>A>>B;
;i<N;i++) cin>>v[i];
return true;
}
void initExp()
{
cnt=;
;i<N;i++)
{
ex[i][]=1LL;
;;j++)
{
ex[i][j]=ex[i][j-]*v[i];
if(ex[i][j]<=B) r[cnt++]=ex[i][j];
else break;
}
}
r[cnt++]=B+;
std::sort(r,r+cnt);
cnt=std::unique(r,r+cnt)-r;
}
Lint gcd(Lint a,Lint b)
{
return b ? gcd(b,a%b) : a;
}
Lint solve_aux(Lint X)
{
Lint ans(0LL);
;i<cnt-;i++)
{
bool ok=true;
;j<N;j++) if(r[i]<v[j])
{ ok=false; break; }
if(!ok) continue;
Lint lcm=1LL;
;j<N;j++)
{
Lint k=0LL;
while(r[i]>=ex[j][k]) k++;
k--;
lcm=lcm*k/gcd(lcm,k);
}
Lint L=r[i],R=r[i+]-;
if(L>X) break;
if(R>=X)
{
R=X; ok=false;
}
if(L%lcm) L+=(lcm-L%lcm);
if(R%lcm) R-=R%lcm;
ans+=(R-L)/lcm+1LL;
if(!ok) break;
}
return ans;
}
Lint solve()
{
initExp();
return solve_aux(B)
-solve_aux(A-);
}
int main()
{
while(input())
cout<<solve()<<"\n";
;
}
Problem:ZOJ P3224
P3231:最小费用流
易证:如果若干个整数的和为定值,那么它们的方差最小时,任意两个数的差不会超过1
于是此题可以转换成有上下界的最小费用流问题
建图方法:对于有流量下界的弧,建两条边:一条流量为其下界,费用为cost-inf;一条流量为上、下界之差,费用为cost(cost为该弧的费用)
对于本题,建立源点与每个节点连边(费用为0,流量为该节点原有的苹果数),树上的边视为双向边建立两条弧(流量为inf,费用为搬运一个苹果的成本),再将每个节点与汇点连边(若苹果总数tot能被N整除,每条边的流量为tot/N,费用为0;否则,按有流量下界的方法建两条边,流量分别为tot/N和1,费用分别为-inf和0)
#include <cstdio>
#include <cstring>
#include <algorithm>
struct Edge
{
int to;
int next;
int capacity;
int cost;
void assign(int t,int n,int ca,int co)
{
to=t; next=n;
capacity=ca;
cost=co;
}
};
;
;
;
;
;
Edge edgeList[maxE];
int head[maxN];
;
void init()
{
memset(head,-,sizeof(head));
edgeCnt=;
}
inline void addEdge(int from,int to,int ca,int co)
{
edgeList[edgeCnt].assign(to,head[from],ca,co);
head[from]=edgeCnt++;
edgeList[edgeCnt].assign(,-co);
head[to]=edgeCnt++;
}
int N;
int ave;
int apple[maxN];
bool exactDiv;
bool input()
{
if(scanf("%d",&N)==EOF) return false;
init();
;i<=N;i++) scanf("%d",apple+i);
; exactDiv=false;
;i<=N;i++) tot+=apple[i];
) exactDiv=true;
;i<=N;i++) addEdge(src,i,apple[i],);
int v1,v2,l;
;i<N;i++)
{
scanf("%d%d%d",&v1,&v2,&l);
++v1; ++v2;
addEdge(v1,v2,inf,l);
addEdge(v2,v1,inf,l);
}
ave=tot/N;
;i<=N;i++)
addEdge(i,sink,ave,);
;i<=N;i++)
{
addEdge(i,sink,ave,-inf);
addEdge(i,sink,,);
}
return true;
}
#include <queue>
const int distInf=0x3f3f3f3f;
std::queue<int> bfsq;
int dist[maxN];
int prev[maxN];
int prevEdge[maxN];
bool inq[maxN];
bool spfa()
{
memset(dist,0x3f,sizeof(dist));
memset(inq,,sizeof(inq));
dist[src]=;
bfsq.push(src);
while(!bfsq.empty())
{
int cur=bfsq.front();
bfsq.pop();
inq[cur]=false;
int t;
;e=edgeList[e].next)
if(edgeList[e].capacity)
{
t=edgeList[e].to;
if(dist[t] > dist[cur] + edgeList[e].cost)
{
dist[t] = dist[cur] + edgeList[e].cost;
prev[t] = cur;
prevEdge[t] = e;
if(!inq[t])
{
inq[t]=true;
bfsq.push(t);
}
}
}
}
return dist[sink]<distInf;
}
int minCostFlow()
{
;
while(spfa())
{
int flow=inf;
int e;
for(int v=sink;v>src;v=prev[v])
{
int e=prevEdge[v];
flow=std::min(flow,edgeList[e].capacity);
}
for(int v=sink;v>src;v=prev[v])
{
e=prevEdge[v];
ans+=flow*edgeList[e].cost;
edgeList[e].capacity-=flow;
edgeList[e^].capacity+=flow;
}
}
return exactDiv ? ans : ans+N*ave*inf;
}
int main()
{
while(input()) printf("%d\n",minCostFlow());
;
}
Problem:ZOJ P3231
P3264:背包问题
#include <cstdio>
#include <cstring>
#include <algorithm>
;
;
int totW,N;
int w1[maxN],w2[maxN],v1[maxN],v2[maxN];
int rel[maxN];
bool input()
{
if(scanf("%d%d",&totW,&N)==EOF)
return false;
totW/=;
;i<=N;i++)
{
scanf("%d%d%d%d%d",w1+i,v1+i,w2+i,v2+i,rel+i);
w1[i]/=; w2[i]/=;
}
return true;
}
int dp[maxW];
int solve()
{
memset(dp,,sizeof(dp));
;i<=N;i++)
{
int j,mn,mx,mv;
switch(rel[i])
{
:
for(j=totW;j>=w1[i]+w2[i];j--)
dp[j]=std::max(dp[j],dp[j-w1[i]-w2[i]]+v1[i]+v2[i]);
break;
:
if(w1[i]<w2[i])
{
mx=w2[i]; mn=w1[i];
mv=;
}
else
{
mx=w1[i]; mn=w2[i];
mv=;
}
for(j=totW;j>=mn;j--)
{
if(j>=mx) dp[j]=std::max(dp[j],
std::max(dp[j-w1[i]]+v1[i],dp[j-w2[i]]+v2[i]));
else dp[j]=std::max(dp[j],
(mv==)?dp[j-w1[i]]+v1[i]:dp[j-w2[i]]+v2[i]);
}
break;
:
for(j=totW;j>=w1[i]+w2[i];j--)
dp[j]=std::max(dp[j],
std::max(dp[j-w1[i]]+v1[i],dp[j-w1[i]-w2[i]]+v1[i]+v2[i]));
for(;j>=w1[i];j--)
dp[j]=std::max(dp[j],dp[j-w1[i]]+v1[i]);
break;
}
}
return dp[totW];
}
int main()
{
while(input()) printf("%d\n",solve());
;
}
Problem:ZOJ P3264
P3279:树状数组+二分
#include <cstdio>
#include <cstring>
#include <algorithm>
;
int bit[maxN];
int pref[maxN];
int cnt[maxN];
int N,Q;
inline int lb(int x)
{
return x & -x;
}
bool input()
{
if(scanf("%d",&N)==EOF) return false;
]=;
;i<=N;i++)
{
scanf("%d",&v);
cnt[i]=v;
pref[i]=pref[i-]+v;
}
;i<=N;i++)
bit[i]=pref[i]-pref[i-lb(i)];
return true;
}
void solve()
{
scanf("%d",&Q);
char cmd;
int ans;
int left,right,mid;
int a,b;
while(Q--)
{
do cmd=getchar(); while(cmd==' ' || cmd=='\n');
if(cmd=='q')
{
scanf("%d",&a);
left=; right=N;
while(left<right)
{
mid=(left+right)>>;
ans=;
for(int i=mid;i;i-=lb(i)) ans+=bit[i];
;
else right=mid;
}
printf("%d\n",left);
}
else
{
scanf("%d%d",&a,&b);
for(int i=a;i<=N;i+=lb(i))
bit[i]+=(b-cnt[a]);
cnt[a]=b;
}
}
}
int main()
{
while(input()) solve();
;
}
Problem:ZOJ P3279
P3280:和2688一个套路
#include <cstdio>
#include <cstring>
#include <algorithm>
;
];
int val[maxN];
];
int N,M;
bool input()
{
if(scanf("%d%d",&N,&M)==EOF) return false;
;i<N;i++)
;j<M;j++)
scanf("%d",dim[i]+j);
;i<M;i++)
scanf("%d",wgt+i);
return true;
}
void setVal(int b)
{
;i<N;i++)
{
val[i]=;
,k=b;j<M;j++,k>>=)
{
) val[i]+=wgt[j]*dim[i][j];
else val[i]-=wgt[j]*dim[i][j];
}
}
}
const int inf=0x70000000;
int solve()
{
int ans=-inf;
;b<(<<M);b++)
{
setVal(b);
int mx=-inf,mn=inf;
;i<N;i++)
{
mx=std::max(mx,val[i]);
mn=std::min(mn,val[i]);
}
ans=std::max(ans,mx-mn);
}
return ans;
}
int main()
{
while(input())
printf("%d\n",solve());
;
}
Problem:ZOJ P3280
P3281:先用spfa求出每个点到起点的距离,然后进行dfs
此题最恶心的地方在于读数据
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <string>
#include <queue>
typedef std::string Str;
;
;
const char* linkTag="Link:";
std::map<Str,int> mp;
char buf[bufLen];
int dist[maxM];
int depth[maxM];
int vis[maxM];
int N,M;
int curIdx;
std::queue<int> que;
struct Edge
{
int to,next;
void assign(int t,int n) { to=t; next=n; }
};
Edge elist[][maxM];
][maxM];
];
void addEdge(int type,int from,int to)
{
)
{
elist[][ecnt[]].assign(to,head[][from]);
head[][]++;
elist[][ecnt[]].assign(][to]);
head[][to]=ecnt[]++;
}
)
{
elist[][ecnt[]].assign(to,head[][from]);
head[][]++;
elist[][ecnt[]].assign(][to]);
head[][to]=ecnt[]++;
}
} //child=0,father=1,linkTo=2,linkFrom=3
void init()
{
memset(head,-,sizeof(head));
memset(ecnt,,sizeof(ecnt));
mp.clear();
curIdx=;
}
bool input()
{
if(scanf("%d%d",&N,&M)==EOF) return false;
N*=M;
scanf("%d",&M);
fgets(buf,bufLen,stdin); //filter '\n'
return true;
}
int readBuf(int pos,int& st,bool& isLink)
{
isLink=true;
;i<;i++) if(buf[pos+i]!=linkTag[i]) isLink=false;
;
for(;buf[pos]!=' ' && buf[pos]!='\n' && buf[pos]!='\0';pos++);
; ;
return pos;
}
inline int check(const Str& s)
{
if(mp.count(s)) return mp[s];
mp.insert(std::map<Str,int>::value_type(s,++curIdx));
return curIdx;
}
inline int move(int n)
{
for(;buf[n]==' ';n++);
return n;
}
void procBuf()
{
Str tp;
),next();
);
int ci,ni;
bool isLink;
next=readBuf(pos,st,isLink);
tp.assign(buf,next);
ci=check(tp);
while(st)
{
pos=move(next);
next=readBuf(pos,st,isLink);
if(isLink)
{
tp.assign(buf+pos+,next-pos-);
ni=check(tp);
addEdge(,ci,ni);
}
else
{
tp.assign(buf+pos,next-pos);
ni=check(tp);
addEdge(,ci,ni);
}
}
}
void link()
{
;i<=M;i++)
{
fgets(buf,bufLen,stdin);
procBuf();
}
}
inline void slack(int from,int to,int len)
{
dist[to]=dist[from]+len;
if(!vis[to])
{
vis[to]=;
que.push(to);
}
}
void spfa()
{
que.push();
memset(vis,,sizeof(vis));
memset(dist,0x3f,sizeof(dist));
dist[]=;
while(!que.empty())
{
int cur=que.front();
que.pop();
vis[cur]=;
][cur];e!=-;e=elist[][e].next)
{
][e].to;
)
slack(cur,to,);
}
][cur];e!=-;e=elist[][e].next)
{
][e].to;
)
slack(cur,to,);
}
][cur];e!=-;e=elist[][e].next)
{
][e].to;
)
slack(cur,to,);
}
}
}
int dfs(int cur,int step)
{
int ans=depth[cur];
][cur];e!=-;e=elist[][e].next)
{
][e].to;
<vis[to] && step++dist[to]<=N)
{
vis[to]=step+;
ans=std::max(ans,dfs(to,step+));
}
}
][cur];e!=-;e=elist[][e].next)
{
][e].to;
<vis[to] && step++dist[to]<=N)
{
vis[to]=step+;
ans=std::max(ans,dfs(to,step+));
}
}
][cur];e!=-;e=elist[][e].next)
{
][e].to;
<vis[to] && step++dist[to]<=N)
{
vis[to]=step+;
ans=std::max(ans,dfs(to,step+));
}
}
return ans;
}
void calcDepth()
{
depth[]=;
que.push();
while(!que.empty())
{
int cur=que.front();
que.pop();
][cur];e!=-;e=elist[][e].next)
{
][e].to;
depth[to]=depth[cur]+;
que.push(to);
}
}
}
int solve()
{
memset(vis,0x3f,sizeof(vis));
vis[]=;
calcDepth();
,);
}
int main()
{
while(input())
{
init();
link();
spfa();
printf("%d\n",solve());
}
;
}
Problem:ZOJ P3281
P3283:有三个要点:
(1)B很大而C很小,所以求a[i]的B次幂无需快速幂算法,直接求循环节即可
(2)通过dp将求和转化为求方案数
dp[x][n]表示对于前x个数,取若干个,其B次幂的乘积取余等于n的方案总数,初始时dp[0][1]=1
注意题目要求不能包含空集,所以dp[N][1]要减1
(3)高精度取余(其实很简单)
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
;
typedef long long int64;
int N,C;
];
];
];
bool input()
{
) return false;
scanf("%s",B);
scanf("%d",&C);
;i<=N;i++)
scanf("%d",A+i);
return true;
}
int Bmod(int x)
{
;
;B[i]!='\0';i++)
res=(*res+(B[i]-'))%x;
return res;
}
void getAs()
{
],vis[];
int len,first;
cyc[]=;
;i<=N;i++)
{
memset(vis,-,sizeof(vis));
vis[]=; len=;
while(len)
{
cyc[len]=cyc[len-]*A[i]%C;
)
{
first=vis[cyc[len]];
break;
}
vis[cyc[len]]=len;
len++;
}
As[i]=cyc[first+Bmod(len-first)];
}
}
int64 dp[][];
int64 solve()
{
getAs();
memset(dp,,sizeof(dp));
dp[][]=;
;i<N;i++)
;j<C;j++)
{
dp[i+][j]+=dp[i][j];
dp[i+][j*As[i+]%C]+=dp[i][j];
}
--dp[N][];
int64 res();
;i<C;i++)
{
res+=i*dp[N][i];
res%=D;
}
return res;
}
int main()
{
while(input())
std::cout<<solve()<<"\n";
;
}
Problem:ZOJ P3283
P3284:维护整行(列)的修改量,可以看成是LazyTag思想的一种体现
#include <cstdio>
#include <cstring>
#include <algorithm>
;
int mat[maxN][maxN];
int deltaR[maxN];
int deltaC[maxN];
int R,C,Q;
bool input()
{
if(scanf("%d%d",&R,&C)==EOF) return false;
;i<=R;i++)
;j<=C;j++)
scanf("%d",mat[i]+j);
return true;
}
void proc()
{
memset(deltaR,,sizeof(deltaR));
memset(deltaC,,sizeof(deltaC));
scanf("%d",&Q);
while(Q--)
{
int cmd; scanf("%d",&cmd);
)
{
int r,c;
scanf("%d%d",&r,&c);
printf("%d\n",mat[r][c]+deltaR[r]+deltaC[c]);
}
else
{
int r1,c1,r2,c2,k;
scanf("%d%d%d%d%d",&r1,&c1,&r2,&c2,&k);
)
{
if(r1==r2) for(int i=c1;i<=c2;i++) mat[r1][i]+=k;
else
{
for(int i=c1;i<=C;i++) mat[r1][i]+=k;
;i<r2;i++) deltaR[i]+=k;
;i<=c2;i++) mat[r2][i]+=k;
}
}
else
{
if(c1==c2) for(int i=r1;i<=r2;i++) mat[i][c1]+=k;
else
{
for(int i=r1;i<=R;i++) mat[i][c1]+=k;
;i<c2;i++) deltaC[i]+=k;
;i<=r2;i++) mat[i][c2]+=k;
}
}
}
}
}
);
int main()
{
while(input())
{
printf("Case %d\n",++cs);
proc();
}
;
}
Problem:ZOJ P3284
P3297:顺序扫描(此题数据特别坑,必须检查合法性)
#include <cstdio>
#include <cstring>
#include <algorithm>
;
;
int N,K;
int C[maxN],A[maxK],B[maxK];
bool input()
{
if(scanf("%d%d",&N,&K)==EOF) return false;
;i<=N;i++) scanf("%d",C+i);
;i<=K;i++) scanf("%d%d",A+i,B+i);
return true;
}
;
int okCnt;
int cnt[maxK];
int head,tail;
int exc;
void init()
{
okCnt=; head=tail=; exc=;
memset(cnt,,sizeof(cnt));
;i<=K;i++)
&& B[i]>=) ++okCnt;
}
bool check()
{
;i<=K;i++)
{
if(A[i]>B[i]) return false;
) return false;
}
return true;
}
int moveHead()
{
++head; int& cur=C[head];
;
++cnt[cur];
if(cnt[cur]==A[cur])
;
)
{
--okCnt;
exc=cur;
;
}
;
}
int moveTail()
{
++tail; int& cur=C[tail];
--cnt[cur];
if(cnt[cur]==B[cur])
{
++okCnt;
; ; }
}
)
{
--okCnt;
) ;
}
;
}
int solve()
{
init();
;
int ans=inf;
;
while(st)
{
if(okCnt==K) ans=std::min(ans,head-tail);
) st=moveHead();
else st=moveTail();
}
:ans;
}
int main()
{
while(input()) printf("%d\n",solve());
;
}
Problem:ZOJ P3297
————To be continued————
ZOJ 刷题记录 (。・ω・)ノ゙(Progress:31/50)的更多相关文章
- ZOJ 刷题记录 小黑屋 (`・д・´)
P1006:模拟 然而我的同余方程能过样例然而就是WA⊙﹏⊙b [已查明:扩展欧几里得算法出了很隐蔽的问题] int exGcd(int x,int y,int& a,int& b) ...
- POJ刷题记录 (。・`ω´・)(Progress:6/50)
1743:前后作差可以转化成不可重叠最长公共字串问题,运用后缀数组解决(参考罗穗骞神犇的论文) #include <cstdio> #include <cstring> #in ...
- PE刷题记录
PE刷题记录 PE60 / 20%dif 这道题比较坑爹. 所有可以相连的素数可以构成一张图,建出这张图,在其中找它的大小为5的团.注意上界的估算,大概在1W以内.1W内有1229个素数,处理出这些素 ...
- leetcode刷题记录--js
leetcode刷题记录 两数之和 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但 ...
- Leetcode刷题记录(python3)
Leetcode刷题记录(python3) 顺序刷题 1~5 ---1.两数之和 ---2.两数相加 ---3. 无重复字符的最长子串 ---4.寻找两个有序数组的中位数 ---5.最长回文子串 6- ...
- 刷题记录:[HarekazeCTF2019]encode_and_encode
目录 刷题记录:[HarekazeCTF2019]encode_and_encode 一.知识点 JSON转义字符绕过 php伪协议 刷题记录:[HarekazeCTF2019]encode_and_ ...
- 刷题记录:[De1CTF 2019]Giftbox && Comment
目录 刷题记录:[De1CTF 2019]Giftbox && Comment 一.知识点 1.sql注入 && totp 2.RCE 3.源码泄露 4.敏感文件读取 ...
- 刷题记录:[强网杯 2019]Upload
目录 刷题记录:[强网杯 2019]Upload 一.知识点 1.源码泄露 2.php反序列化 刷题记录:[强网杯 2019]Upload 题目复现链接:https://buuoj.cn/challe ...
- 刷题记录:[XNUCA2019Qualifier]EasyPHP
目录 刷题记录:[XNUCA2019Qualifier]EasyPHP 解法一 1.error_log结合log_errors自定义错误日志 2.include_path设置包含路径 3.php_va ...
随机推荐
- maven配置默认jdk版本
在maven的默认配置中,对于jdk的配置是1.4版本,那么创建/导入maven工程过程中,工程中未指定jdk版本. 对工程进行maven的update,就会出现工程依赖的JRE System Lib ...
- 什么是系统,什么是算法 -- lemon OA 系统学习总结
一.对于模块划分的理解 对于一个大型(这里还只是一个中型系统)系统来说,代码的编写不是一日而就的,层次的明细也不是一眼就能看清楚的. 在这种情况下,需要想好,最好是由上而下地想好. 能够模块式地划分最 ...
- 最棒的Visual Studio扩展
isual Studio是微软公司推出的开发环境,Visual Studio可以用来创建Windows平台下的Windows应用程序和网络应用程序,也可以用来创建网络服务.智能设备应用程序和Offic ...
- 【狼】unity3d iTween插件的学习
之前在一个三消游戏项目中接触到iTween,最近又要用到,发现iTween真的是一个很好用,省事的插件,有很多函数里包括 Hashtable的他都用一个函数很简单的完成了, 举几个例子 void Lo ...
- MySQL可视化管理工具 —— Navicat for MysSQL
类似PL/SQL管理Oracle的工具 Navicat可以管理MySQL 1.安装 2.连接(输入IP.端口.用户名.密码) 3.新建sql语句:点击左侧database.点击菜单“查询”.点击“新建 ...
- hud 1241 dfs连同块
Problem Description The GeoSurvComp geologic survey company is responsible for detecting underground ...
- Java中json工具对比分析
Java中几个json工具分析 1, 环境 JDK1.6+IDE(IntelliJ IDEA)+windowsXP+GBK编码 2,分析对象 jackson1.8.2 http://jackson.c ...
- sql 数据字段类型
bit 整型 bit数据类型是整型,其值只能是0.1或空值.这种数据类型用于存储只有两种可能值的数据,如Yes 或No.True 或False .On 或Off. 注意:很省空间的一种数据类型, ...
- C++ —— 时间与日期
导读 在平时编程中有时需要获取当前的时间或者日期,然而不同的平台不同的场景下,有时使用的API也不尽相同.一般来说,C/C++中关于时间的标准库函数在不同的平台的都可以使用,可一些与平台相关的函数就只 ...
- 浙江大学PAT上机题解析之1014. 福尔摩斯的约会 (20)
1014. 福尔摩斯的约会 (20) 时间限制 50 ms 内存限制 32000 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Y ...