标签:
觉得做一道开一篇真不好...好多想找的东西都被刷下去了...
至于?的日期究竟到什么时候...还是看心情...但是估计不会超过七天吧
05.12
当然是用刷水题来开启新的一天><
感觉啊...这道题怎么做都可以..所以索性不说了
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<cmath> 5 #define INF 1000000007 6 #define maxn 150010 7 struct node{ 8 int x,y; 9 }a[maxn]; 10 int n,f[maxn][25],m; 11 void swap(int &x,int &y){ 12 int tmp=x;x=y;y=tmp; 13 } 14 int getl(int x){ 15 int l=1,r=n,ans=0; 16 while (l<=r){ 17 int mid=(l+r) >> 1; 18 if (a[mid].x<x) ans=mid,l=mid+1;else r=mid-1; 19 } 20 return ans; 21 } 22 int getr(int x){ 23 int l=1,r=n,ans=n+1; 24 while (l<=r){ 25 int mid=(l+r)>>1; 26 if (a[mid].x>x) ans=mid,r=mid-1;else l=mid+1; 27 } 28 return ans; 29 } 30 int find(int x){ 31 int l=1,r=n; 32 while (l<=r){ 33 int mid=(l+r)>>1; 34 if (a[mid].x==x) return mid; 35 if (x<a[mid].x) r=mid-1;else l=mid+1; 36 } 37 return -1; 38 } 39 int max(int a,int b){ 40 if (a>b) return a; 41 return b; 42 } 43 int getmax(int x,int y){ 44 if (x>y) return -INF; 45 int tmp=(int)(log(y-x+1)/log(2)); 46 return max(f[x][tmp],f[y-(1<<tmp)+1][tmp]); 47 } 48 int main(){ 49 scanf("%d",&n); 50 for (int i=1;i<=n;i++)scanf("%d%d",&a[i].x,&a[i].y),f[i][0]=a[i].y; 51 for (int j=1;1<<j<=n;j++) 52 for (int i=1;i<=n;i++) f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))][j-1]); 53 scanf("%d",&m); 54 int x,y; 55 for (int i=1;i<=m;i++){ 56 scanf("%d%d",&x,&y); 57 int lx=find(x),ly=find(y); 58 if (lx==-1&&ly==-1) printf("maybe");else 59 if (lx>0&&ly==-1){ 60 if (getmax(getr(x),getl(y))<a[lx].y) printf("maybe");else printf("false"); 61 }else 62 if (lx==-1&&ly>0){ 63 if (getmax(getr(x),getl(y))<a[ly].y) printf("maybe");else printf("false"); 64 }else{ 65 if (getmax(getr(x),getl(y))<a[ly].y&&a[lx].y>=a[ly].y){ 66 if (ly-lx==y-x) printf("true");else printf("maybe"); 67 }else printf("false"); 68 } 69 printf("\n"); 70 } 71 return 0; 72 }
由于一个下标写错调了好久..对拍出错的数据还因为脑抽手算不出正解..
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 char s[110]; 5 int n,g[110][110]; 6 int min(int a,int b){ 7 if (a<b) return a; 8 return b; 9 } 10 bool comp(int l1,int r1,int l2,int r2){ 11 int j=l2; 12 for (int i=l1;i<=r1;i++){ 13 if (s[i]!=s[j]) return false; 14 j++;if (j>r2) j=l2; 15 } 16 return true; 17 } 18 int calc(int l,int r){ 19 if (g[l][r]) return g[l][r]; 20 int f[110]; 21 f[0]=0; 22 for (int i=1;i<=r-l+1;i++){ 23 f[i]=f[i-1]+1; 24 for (int j=1;j<=i;j++) 25 for (int k=1;(1<<k)*j<=i;k++) if (comp(l-1+i-(1<<k)*j+1,l-1+i-j*(1<<(k-1)),l-1+i-j+1,l-1+i)){ 26 if (i-(1<<k)*j+1==1) f[i]=min(f[i],f[0]+k+calc(l-1+i-j+1,l-1+i));else{ 27 if (l==1) f[i]=min(f[i],f[i-(1<<k)*j]+k+calc(l+i-j,l+i-1)+1); 28 } 29 }else break; 30 } 31 g[l][r]=f[r-l+1]; 32 return g[l][r]; 33 } 34 int main(){ 35 scanf("%s",s+1); 36 int n=strlen(s+1); 37 printf("%d\n",calc(1,n)); 38 return 0; 39 }
然后啊..就去跟随wjz、qwer、yu990601等大爷的步伐去做TJOI啦
好像是SAM比较简单的应用,但是做的过程中还是发现自己对于算法本身有些地方理解得不够
感谢黄学长的解答
还是意料之内地TLE了几发...想起JYW一周前给我提的建议啊
由于很多以前的习惯导致随手memset,然后数组喜欢开大好几倍,看着不大顺眼的数组就开long long...
上次HNOI的两道题好像JYW就是帮我改了这样几个地方然后过掉的呢...
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #define maxn 1000010 5 #define ll long long 6 int cnt,root,fail[maxn],a[maxn][26],v[maxn/2],q[maxn],mx[maxn],t,k,n; 7 char s[maxn/2]; 8 int sum[maxn],val[maxn]; 9 int insert(int p,int c){ 10 int np=++cnt;mx[np]=mx[p]+1;val[np]=1; 11 while (p!=0&&a[p][c]==0) a[p][c]=np,p=fail[p]; 12 if (p==0) fail[np]=root;else 13 { 14 int q=a[p][c]; 15 if (mx[q]==mx[p]+1) fail[np]=q;else{ 16 int nq=++cnt;mx[nq]=mx[p]+1; 17 for (int i=0;i<26;i++) a[nq][i]=a[q][i];fail[nq]=fail[q]; 18 fail[np]=fail[q]=nq; 19 while (a[p][c]==q) a[p][c]=nq,p=fail[p]; 20 } 21 } 22 return np; 23 } 24 void pre(){ 25 for (int i=1;i<=cnt;i++) v[mx[i]]++; 26 for (int i=1;i<=n;i++) v[i]+=v[i-1]; 27 for (int i=1;i<=cnt;i++) q[v[mx[i]]--]=i; 28 for (int i=cnt;i;i--){ 29 int p=q[i]; 30 if (t==1) val[fail[p]]+=val[p];else val[p]=1; 31 } 32 val[root]=0; 33 for (int i=cnt;i;i--){ 34 int p=q[i];sum[p]=val[p]; 35 for (int j=0;j<26;j++) sum[p]+=sum[a[p][j]]; 36 } 37 } 38 void dfs(int p){ 39 if (val[p]>=k) return; 40 k-=val[p]; 41 for (int i=0;i<26;i++) if (a[p][i]){ 42 int u=a[p][i]; 43 if (sum[u]<k) k-=sum[u];else 44 { 45 printf("%c",i+97); 46 dfs(u);return; 47 } 48 } 49 } 50 int main(){ 51 scanf("%s",s+1); 52 n=strlen(s+1); 53 scanf("%d%d",&t,&k); 54 root=1;cnt=1;int las=root; 55 for (int i=1;i<=n;i++) las=insert(las,s[i]-97); 56 pre(); 57 if (sum[root]<k) printf("-1");else dfs(root); 58 return 0; 59 }
Dilworth定理:DAG的最小链覆盖=最大点独立集
然后就很水辣
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 1010 6 using namespace std; 7 int T,n,m,f[maxn][maxn],a[maxn][maxn]; 8 int main(){ 9 scanf("%d",&T); 10 while (T--){ 11 scanf("%d%d",&n,&m); 12 for (int i=1;i<=n;i++) 13 for (int j=1;j<=m;j++) scanf("%d",&a[i][j]); 14 memset(f,0,sizeof(f)); 15 for (int i=1;i<=n;i++) 16 for (int j=m;j;j--) f[i][j]=max(max(f[i-1][j+1]+a[i][j],f[i][j+1]),f[i-1][j]); 17 printf("%d\n",f[n][1]); 18 } 19 }
题目中的式子最终可以化成这个样子
(我不会用编辑器啊...
然后A是一行01的数组,就可以很容易地想到是代表取与不取的状态
也就是bij表示第i件物品与第j件物品都取能获得的收益
然后ci表示第i件物品的价格
然后用网络流做...
为什么他们的点数都是n^2的呢...?
先说下我的做法吧
点数(2n+2) 边数(n^2+2n)
把每个点拆成代表取与不取两个状态的两个点,之间连上容量为正无穷的边
对于代表不取的边,很显然,向汇点连一条容量为价格的边
然后考虑bij的处理方法看这样三种情况
第一种就是都取..这个和b无关..
第二种是都不取,这个时候我们需要减掉的是(b[a,b]+b[b,a])(于是悲伤地重名了..不过没关系
也就是我们要令叉掉的两条边容量=这个数
第三种是取其中一个,图中画的是取a的示意,与t相连的已经考虑过了
这个时候需要减掉的依然是(b[a,b]+b[b,a]),然后叉掉的也是两条边...
然后做法好像就很显然了...把(b[a,b]+b[b,a])/2的容量分给每一条与s相连,以及两点之间相连的边
为了方便处理我们把它乘上2,然后最后答案除以2
然而啊由于边数比较大,刚开始较是T掉的
本地自己造了一组极限数据,发现要跑4s左右
加了当前弧优化之后还是要3s
然后在dfs结束之后如果流量为0就把dis修改掉
居然眨眼就出解了呢...
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<algorithm> 5 #define maxn 1010 6 #define maxm 520010 7 #define INF 1000000007 8 using namespace std; 9 int link[maxn],ter[maxm],next[maxm],w[maxm],rec[maxm],cur[maxn],opt[maxn],dis[maxn],n,e,s,t,b[maxn],a[maxn][maxn],c[maxn]; 10 bool vis[maxn]; 11 void add(int x,int y,int z){ 12 ter[++e]=y;next[e]=link[x];link[x]=e;w[e]=z;rec[e]=e+1; 13 ter[++e]=x;next[e]=link[y];link[y]=e;w[e]=0;rec[e]=e-1; 14 } 15 bool spfa(){ 16 memset(vis,true,sizeof(vis)); 17 memset(dis,INF,sizeof(dis)); 18 int head=0,tail=1;opt[1]=s;dis[s]=0;vis[s]=false; 19 while (head!=tail){ 20 int x=opt[head=(head+1)%maxn]; 21 for (int i=link[x];i;i=next[i]) if (w[i]>0&&dis[x]+1<dis[ter[i]]){ 22 dis[ter[i]]=dis[x]+1; 23 if (vis[ter[i]]) vis[ter[i]]=false,opt[(tail+1)%maxn]=ter[i],tail=(tail+1)%maxn; 24 } 25 vis[x]=true; 26 } 27 if (dis[t]!=dis[t+1]) return true; 28 return false; 29 } 30 int dfs(int p,int sum){ 31 int tmp=0; 32 if (p==t) return sum; 33 for (int i=cur[p];i;i=next[i])if (dis[ter[i]]==dis[p]+1&&w[i]>0){ 34 int x=dfs(ter[i],min(w[i],sum-tmp)); 35 w[i]-=x;w[rec[i]]+=x;tmp+=x; 36 if (w[i]>0) cur[p]=i; 37 if (tmp==sum) return sum; 38 } 39 if (tmp==0) dis[p]=-2; 40 return tmp; 41 } 42 int dinic(){ 43 int sum=0; 44 while (spfa()){ 45 for (int i=s;i<=t;i++) cur[i]=link[i]; 46 sum+=dfs(s,INF); 47 } 48 return sum; 49 } 50 int main(){ 51 scanf("%d",&n); 52 int ans=0; 53 for (int i=1;i<=n;i++) 54 for (int j=1;j<=n;j++) scanf("%d",&a[i][j]),ans+=a[i][j]; 55 for (int i=1;i<=n;i++) 56 for (int j=1;j<=n;j++) b[i]+=a[i][j]+a[j][i]; 57 for (int i=1;i<=n;i++) scanf("%d",&c[i]); 58 s=0;t=2*n+1;e=0; 59 for (int i=1;i<=n;i++){ 60 add(s,i,b[i]);add(n+i,t,c[i]*2); 61 for (int j=1;j<=n;j++) if (i!=j) add(i,n+j,a[i][j]+a[j][i]); 62 add(i,n+i,INF); 63 } 64 ans=ans*2; 65 ans-=dinic(); 66 printf("%d\n",ans/2); 67 return 0; 68 }
标签:
原文地址:http://www.cnblogs.com/mjy0724/p/4498375.html