怎么发一次格式抽一次
T1
打表发现答案小于n
考虑求出S,T的最小割,并且提取出在S这一边和在T这一边的点集
考虑S'属于S这一边的点集,T'属于T这一边的点集,那么S'和T'的最小割可以用其他两个点代替
借助bzoj2229黄学长的一句话:
注意这样一个事实:如果(X,Y)是某个s1-t1最小割,(Z,W)是某个s2-t2最小割,那么X∩Z、X∩W、Y∩Z、Y∩W这四项不可能均非空。也就是说,最小割不可能相互跨立。
这个蕴含了,最多一共有N-1个不同的s-t最小割。只需把这些割找出来即可。
寻找的方法:首先,在V中任意找两个点a,b,求最大流,把V划分为割X-Y,之后对X、Y分别递归地进行划分。这样就能得到N-1个割了。
那么我们可以分治求最小割,这样求得的最小割一定能够代表所有的最小割
T2
第一种:考场上YY出来的,因为太懒所以没写
首先求凸包,求出凸包上每一个点所能到达的最远点,push到堆中
对全局维护一个堆,每次弹出最大值,然后讲两个点的次远点在kd树中找出来
找出来的复杂度是sqrt(n)的,外加二份答案,共k次,总复杂度k*sqrt(n)*log(没有代码)
第二种
还是求出凸包和每一个点所能到达的最远点,每次拿出堆中的时候暴力扫n个点,强行插入次远的点
所以下面这个是nklog的。也能过
T3
傻逼数位dp
dp[当前位数][是否有8][是否有4][上一位][连续几位][已经有没有3位连续的][是否达到上限]
dfs一遍记忆化转移就好
顺便说一句,函数记得return啊!!!关键是小数据还是对的调崩我了
代码
T1
//Copyright(c)2016 liuchenrui
#include<bits/stdc++.h>
#define short unsigned short
#define inf 1000000000
using namespace std;
template<typename T>
inline void splay(T &v){
v=0;char c=0;T p=1;
while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
v*=p;
}
struct Edge{
short to,next;int flow;
}edge[100010];
short first[851],size;
short deep[851],dl[851];
void addedge(short x,short y,int z){
size++;
edge[size].to=y;
edge[size].next=first[x];
first[x]=size;
edge[size].flow=z;
}
void add(short x,short y,int z){
addedge(x,y,z),addedge(y,x,0);
}
short aim;
int dfs(short now,int flow){
if(now==aim)return flow;
int F=0;
for(short u=first[now];u&&flow;u=edge[u].next){
if(deep[edge[u].to]==deep[now]+1&&edge[u].flow){
int tmp=dfs(edge[u].to,min(flow,edge[u].flow));
F+=tmp;edge[u].flow-=tmp;edge[u^1].flow+=tmp;flow-=tmp;
}
}
if(!F)deep[now]=-5;
return F;
}
bool bfs(short S,short T){
memset(deep,0,sizeof(deep));
dl[1]=S;deep[S]=1;
short head=0,tail=1;
while(head!=tail){
head++;
for(int u=first[dl[head]];u;u=edge[u].next){
if(!deep[edge[u].to]&&edge[u].flow){
dl[++tail]=edge[u].to;
deep[edge[u].to]=deep[dl[head]]+1;
}
}
}
return deep[T];
}
int maxflow(short S,short T){
int ret=0;aim=T;
while(bfs(S,T)){
ret+=dfs(S,inf);
}
return ret;
}
short fr[8600],to[8600];
int fl[8600];
int ans[1000010];
short cnt,n,m,p[851];
void rebuild(){
memset(first,0,sizeof first);
size=1;
for(int k=1;k<=m;k++){
add(fr[k],to[k],fl[k]);
add(to[k],fr[k],fl[k]);
}
}
bool vis[860];
void dfs2(short now){
vis[now]=1;
for(int u=first[now];u;u=edge[u].next){
if(edge[u].flow&&!vis[edge[u].to]){
dfs2(edge[u].to);
}
}
}
void cdq_calc(short l,short r){
if(l>=r)return;
rebuild();
ans[++cnt]=maxflow(p[l],p[r]);
memset(vis,0,sizeof vis);
dfs2(p[l]);int t=l-1;
for(short i=l;i<=r;i++){
if(vis[p[i]]){
swap(p[i],p[++t]);
}
}
cdq_calc(l,t),cdq_calc(t+1,r);
}
int main(){
freopen("cuts.in","r",stdin);
freopen("cuts.out","w",stdout);
splay(n),splay(m);
for(short i=1;i<=m;i++){
splay(fr[i]),splay(to[i]),splay(fl[i]);
}
for(short i=1;i<=n;i++){
p[i]=i;
}
cdq_calc(1,n);
sort(ans+1,ans+cnt+1);
cnt=unique(ans+1,ans+cnt+1)-ans-1;
printf("%d\n",cnt);
//cerr<<clock()<<endl;
}
T2是czh的代码,自己的WA没调出来
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <map>
#define inf (((unsigned long long)1 << (unsigned long long)63) - (unsigned long long)1)
#define Int long long
using namespace std;
struct point {Int x;Int y;int id;
};point p[100010],q[100010],stack[200010];
Int val[800010],minx[850],maxx[850];
int E,belong[100010],cnt,n,k;
int head,tail,father[100010],t,num[100010];
int tot[850];
map < pair<int,int>,int> mp;
Int calc(point x,point y,point z) {
point A,B;
A.x = x.x - z.x;
A.y = x.y - z.y;
B.x = y.x - z.x;
B.y = y.y - z.y;
return A.x * B.y - A.y * B.x;
}
Int dis(point x,point y) {
Int ret = (x.x - y.x) * (x.x - y.x) + (x.y - y.y) * (x.y - y.y);
return ret;
}
bool comp(const point &x,const point &y) {
Int v = calc(x,y,p[1]);
if(v == 0) return dis(x,p[1]) < dis(y,p[1]);
return v > 0;
}
void build(int Now,int l,int r) {
val[Now] = -1;
if(l == r) return;
int Mid = (l + r) >> 1;
build(Now << 1,l,Mid);
build(Now << 1 | 1,Mid + 1,r);
}
void change(int Now,int l,int r,int x,Int y) {
if(l == r) {val[Now] = y;return ;}
int Mid = (l + r) >> 1;
if(x <= Mid) change(Now << 1,l,Mid,x,y);
else change(Now << 1 | 1,Mid + 1,r,x,y);
if(val[Now << 1] > val[Now << 1 | 1])
val[Now] = val[Now << 1];
else val[Now] = val[Now << 1 | 1];
}
int Ask(int Now,int l,int r) {
if(l == r) return r;
int Mid = (l + r) >> 1;
if(val[Now << 1] == val[Now])
return Ask(Now << 1,l,Mid);
else return Ask(Now << 1 | 1,Mid + 1,r);
}
int find(int Now,int l,int r) {
if(l == r) return r;
int Mid = (l + r) >> 1;
if(minx[Now] == minx[Now << 1])
return find(Now << 1,l,Mid);
else return find(Now << 1 | 1,Mid + 1,r);
}
void insert(int Now,int l,int r,int x,Int y) {
if(l == r) {minx[Now] = maxx[Now] = y;tot[Now] = 1;return ;}
int Mid = (l + r) >> 1;
if(x <= Mid) insert(Now << 1,l,Mid,x,y);
else insert(Now << 1 | 1,Mid + 1,r,x,y);
tot[Now] = tot[Now << 1] + tot[Now << 1 | 1];
minx[Now] = min(minx[Now << 1],minx[Now << 1 | 1]);
maxx[Now] = max(maxx[Now << 1],maxx[Now << 1 | 1]);
}
int bf(int x) {
int Z = num[x] + 1;
for(int i = 1;i <= 810;i ++)
minx[i] = inf,maxx[i] = -1,tot[i] = 0;
for(int i = 1;i <= n;i ++)
{
Int G = dis(q[i],q[x]);
if(tot[1] < Z)
insert(1,1,100,tot[1] + 1,G);
else if(minx[1] < G)
insert(1,1,100,find(1,1,100),G);
}
for(int i = 1;i <= n;i ++)
if(dis(q[i],q[x]) == minx[1] && mp[make_pair(x,i)] == 0)
return i;
}
int getint() {
char c = 'd';
int ret = 0;
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') ret = ret * 10 + c - '0',c = getchar();
return ret;
}
int main() {
freopen("farthest.in","r",stdin);
freopen("farthest.out","w",stdout);
n = getint();
k = getint();
for(int i = 1;i <= n;i ++)
p[i].x = getint(),p[i].y = getint(),q[i].x = p[i].x,q[i].y = p[i].y,p[i].id = i;
t = 1;
for(int i = 2;i <= n;i ++)
if(p[i].y < p[t].y || (p[i].y == p[t].y && p[i].x < p[t].x))
t = i;
swap(p[1],p[t]);
sort(p + 2,p + n + 1,comp);
head = 1;tail = 0;
for(int i = 1;i <= n;i ++)
{
while(head < tail && calc(p[i],stack[tail],stack[tail - 1]) > 0)
tail --;
stack[ ++ tail] = p[i];
}
for(int i = 1;i <= tail;i ++)
stack[i + tail] = stack[i];
int M = 1;
build(1,1,n);
for(int i = 1;i <= tail;i ++)
{
while(M < 2 * tail && dis(stack[M + 1],stack[i]) > dis(stack[M],stack[i]))
M = M + 1;
change(1,1,n,stack[i].id,dis(stack[i],stack[M]));father[stack[i].id] = stack[M].id;
}
for(int i = 1;i < k;i ++)
{
int t = Ask(1,1,n),w = father[t];
mp[make_pair(w,t)] = mp[make_pair(t,w)] = 1;
num[t] ++;
num[w] ++;
father[t] = bf(t);
father[w] = bf(w);
change(1,1,n,t,dis(q[t],q[father[t]]));
change(1,1,n,w,dis(q[w],q[father[w]]));
}
cout<<val[1];
}
T3
//Copyright(c)2016 liuchenrui
#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline void splay(int &v){
v=0;char c=0;int p=1;
while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
v*=p;
}
int s[15];
LL dp[13][2][2][10][12][2][10];//当前位数,是否有8,是否有4,上一位,连续几位,已经有没有3位连续的,是否达到上限
LL dfs(int a,int b,int c,int d,int e,int f,int g){
if(a>11){
if(b&&c)return 0;
if(!f)return 0;
return 1;
}
if(dp[a][b][c][d][e][f][g]!=-1)return dp[a][b][c][d][e][f][g];
LL ret=0;int t;
if(g==0){
for(int i=0;i<=9;i++){
if(i==d)t=e+1;else t=1;
ret+=dfs(a+1,(b|(i==8)),(c|(i==4)),i,t,(t>=3)|(f),0);
}
}
else{
for(int i=0;i<s[a];i++){
if(i==d)t=e+1;else t=1;
ret+=dfs(a+1,(b|(i==8)),(c|(i==4)),i,t,(t>=3)|(f),0);
}
if(s[a]==d)t=e+1;else t=1;
ret+=dfs(a+1,(b|(s[a]==8)),(c|(s[a]==4)),s[a],t,(t>=3)|(f),1);
}
return dp[a][b][c][d][e][f][g]=ret;
}
LL calc(LL a){
if(a<10000000000LL)return 0;
for(int i=11;i>=1;i--){
s[i]=a%10;a/=10;
}
memset(dp,-1,sizeof dp);
LL ret=0;
for(int i=1;i<s[1];i++){
ret+=dfs(2,i==8,i==4,i,1,0,0);
}
ret+=dfs(2,s[1]==8,s[1]==4,s[1],1,0,1);
return ret;//nmb 记得return啊卧槽!!!!!!!
}
int main(){
freopen("number.in","r",stdin);
freopen("number.out","w",stdout);
LL x,y;
cin>>x>>y;
LL a=calc(x-1);
LL b=calc(y);
cout<<b-a<<endl;
}