码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ做题记录[0512~?]

时间:2015-05-12 20:58:34      阅读:277      评论:0      收藏:0      [点我收藏+]

标签:

  觉得做一道开一篇真不好...好多想找的东西都被刷下去了...

  至于?的日期究竟到什么时候...还是看心情...但是估计不会超过七天吧

 

 


 

 

  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件物品的价格

  然后用网络流做...

 

  但是看了几个人的blog(这里 这里 

  为什么他们的点数都是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 }

 

  

 

  

  

 

 

  

  

  

  

BZOJ做题记录[0512~?]

标签:

原文地址:http://www.cnblogs.com/mjy0724/p/4498375.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!