怎么发一次格式抽一次
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]; }
//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; }