zoukankan      html  css  js  c++  java
  • TJOI2015 day1解题报告

    博客园的编辑器真的是太蛋疼了= =,想用tex然后上jpg又贴不了链接,真的很纠结啊= =

    T1:[TJOI2015]线性代数

    描述:戳上面吧= =

    首先这道题我觉得是这套题最漂亮的一道题了(虽然说学校的题库里居然有一道和这个一模一样的= =)

    首先我们可以先把那个式子转化为其中b[i]是表示矩阵a中第i行为0或为1,然后就有两种方法转化为网络流啦

    方法一:可以用最大权闭合子图的方法来考虑,将c[i]以及a[i][j]的选择与否视为事件的话,可以发现是一个点数为n*n的最大权闭合子图,就可以愉快的用网络流来搞辣

    方法二:我们可以看做一个二元关系,因为可以看做i的选取会花费 c[i],而同时选择i, j则会获得一定的收益,那么我们可以得到一个二元关系(但还是需要经过一定的转化的),然后点数就只有n啦

    我只写了方法一,虽说点数很多,但边数少,还是很快的

    还有一种水法,貌似直接把所有a相加然后减去b就行辣(数据就是这么水= =)

    CODE:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 #define maxn 300000
     7 #define maxm 900000
     8 struct edges{
     9     int to,next,cap;
    10 }edge[maxm*2];
    11 int next[maxn],l;
    12 inline void addedge(int x,int y,int z) {
    13     l++;
    14     edge[l*2]=(edges){y,next[x],z};next[x]=l*2;
    15     edge[l*2+1]=(edges){x,next[y],0};next[y]=l*2+1;
    16 }
    17 #define inf 0x7fffffff
    18 int s,t,h[maxn],p[maxn],gap[maxn];
    19 int sap(int u,int flow) {
    20     if (u==t) return flow;
    21     int cnt=0;
    22     for (int i=p[u];i;i=edge[i].next) 
    23         if (edge[i].cap&&h[u]==h[edge[i].to]+1) {
    24             int cur=sap(edge[i].to,min(flow-cnt,edge[i].cap));
    25             edge[i].cap-=cur;edge[i^1].cap+=cur;
    26             p[u]=i;
    27             if ((cnt+=cur)==flow) return cnt;
    28         }
    29     if (!(--gap[h[u]])) h[s]=t;
    30     gap[++h[u]]++;
    31     p[u]=next[u];
    32     return cnt;
    33 }
    34 inline int maxflow(){
    35     for (int i=1;i<=t;i++) p[i]=next[i];
    36     memset(gap,0,sizeof(gap));
    37     memset(h,0,sizeof(h));
    38     gap[0]=t;
    39     int flow=0;
    40     while (h[s]<t) flow+=sap(s,inf);
    41     return flow;
    42 }
    43 int id[510][510],cnt,n;
    44 int main(){
    45     freopen("algebra.in","r",stdin);
    46     freopen("algebra.out","w",stdout);
    47     scanf("%d",&n);
    48     for (int i=0;i<=n;i++) 
    49         for (int j=1;j<=n;j++) id[i][j]=++cnt;
    50     s=++cnt,t=++cnt;
    51     int sum=0;
    52     for (int i=1;i<=n;i++) 
    53         for (int j=1;j<=n;j++) {
    54             int x;
    55             scanf("%d",&x);
    56             addedge(s,id[i][j],x);
    57             sum+=x;
    58         }
    59     for (int i=1;i<=n;i++) {
    60         int x;
    61         scanf("%d",&x);
    62         addedge(id[0][i],t,x);
    63     }
    64     for (int i=1;i<=n;i++) 
    65         for (int j=1;j<=n;j++) {
    66             addedge(id[i][j],id[0][i],inf);
    67             addedge(id[i][j],id[0][j],inf);
    68         }
    69     printf("%d
    ",sum-maxflow());
    70     return 0;
    71 }
    View Code

    T2:[TJOI2015]组合数学

    这是道结论题= =

    某个啥啥定理说:DAG的最小链覆盖=最大独立点集,可见网格图的最大独立点集一定是从右上到左下的一条路径,那么我们就可以直接dp搞了

    CODE:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 #define maxn 1100
     7 int f[maxn][maxn],a[maxn][maxn],T,n,m;
     8 int main(){
     9     freopen("math.in","r",stdin);
    10     freopen("math.out","w",stdout);
    11     scanf("%d",&T);
    12     while (T--) {
    13         memset(f,0,sizeof(f));
    14         scanf("%d%d",&n,&m);
    15         for (int i=1;i<=n;i++) 
    16             for (int j=1;j<=m;j++) scanf("%d",a[i]+j);
    17             int ans=0;
    18         for (int i=n;i;i--) 
    19             for (int j=1;j<=m;j++) {
    20                 f[i][j]=max(f[i][j-1],max(f[i+1][j-1]+a[i][j],f[i+1][j]));
    21                 ans=max(ans,f[i][j]);
    22             }
    23         printf("%d
    ",ans);
    24     }
    25     return 0;
    26 }
    View Code

    T3:[TJOI2015]弦论

    这道题嘛= =,50分算法是深圳市选题,然后100分的话我们可以用SAM来解决这个问题

    首先我们先来考虑一下50分的算法,SAM上的每一个节点都表示该图中的一个子串,所以我们可以类似dp求出答案

    而对于T=1的时候,可以发现重复的字串其实都在以parents树上该节点为根的子树

    所以我们还是可以dp一下求出来

    八中上被卡常数了,老调不出来

    CODE:

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cstring>
      5 using namespace std;
      6 #define maxn 1001000
      7 char s[maxn];
      8 typedef long long ll;
      9 struct sam{
     10     sam *pre,*ch[26];
     11     int val,cnt;ll size;
     12     bool b;
     13 }_t[maxn];
     14 sam *root,*last;
     15 int t,cnt;
     16 inline void add(int x) {
     17     sam *p=last;
     18     _t[++cnt].val=last->val+1;
     19     sam *np=_t+cnt;
     20     while (p&&p->ch[x]==0) p->ch[x]=np,p=p->pre;
     21     if (p==0) np->pre=root;
     22     else {
     23         sam* q=p->ch[x];
     24         if (p->val+1==q->val) np->pre=q;
     25         else {
     26             _t[++cnt].val=p->val+1;
     27             sam*nq=_t+cnt;
     28             memcpy(nq->ch,q->ch,sizeof(q->ch));
     29             nq->pre=q->pre;
     30             np->pre=q->pre=nq;
     31             while (p&&p->ch[x]==q) p->ch[x]=nq,p=p->pre;
     32         }
     33     }
     34     last=np;
     35 }
     36 inline void bfs(){
     37     static sam* q[maxn];
     38     q[1]=root;
     39     sam* u=q[1];
     40     int l,r;
     41     for (l=r=1;l<=r;u=q[++l]) {
     42         for (int i=0;i<26;i++) {
     43             if (!u->ch[i]||u->ch[i]->b) continue;
     44                u->ch[i]->b=1;
     45                q[++r]=u->ch[i];
     46         }
     47     }
     48     u=q[r];
     49     for (int i=r;i;u=q[--i]) {
     50         if (!t) u->cnt=1;
     51         if (i==1) u->cnt=0;
     52         if (u->pre) u->pre->cnt+=u->cnt;
     53     }
     54 }
     55 char ans[maxn];
     56 int l;
     57 void dfs(sam *p){
     58     int i;
     59     p->b=0;
     60     p->size=p->cnt;
     61     for(i=0;i<26;i++)
     62         if(p->ch[i]){
     63             if(p->ch[i]->b==1) dfs(p->ch[i]);
     64              p->size+=p->ch[i]->size;
     65         }
     66 }
     67 int k;
     68 void get(sam *p){
     69     int i;
     70     if(k<=p->cnt) return ;
     71     k-=p->cnt;
     72     for(i=0;i<26;i++)
     73         if(p->ch[i]){
     74             if(k<=p->ch[i]->size){
     75                ans[++l]=i+'a';
     76                get(p->ch[i]);
     77                return ;
     78            }
     79            k-=p->ch[i]->size;
     80        }
     81 }
     82 int main(){
     83     scanf("%s%d%d",&s,&t,&k);
     84     root=_t;
     85     root->val=1;last=root;
     86     int n=strlen(s);
     87     for (int i=0;i<n;i++) {
     88         add(s[i]-'a');
     89         last->cnt=1;
     90     }
     91     bfs();
     92     dfs(root);
     93     if (root->size<k) {
     94         printf("-1
    ");
     95         return 0;
     96     }
     97     get(root);
     98     printf("%s
    ",ans+1);
     99     return 0;
    100 }
    View Code
  • 相关阅读:
    迁移学习综述
    分析 Kaggle TOP0.1% 如何处理文本数据
    软件工程提问回顾与个人总结
    洛谷 4219/BZOJ 4530 大融合
    洛谷 1486/BZOJ 1503 郁闷的出纳员
    【模板】文艺平衡树
    【模板】树套树(线段树套Splay)
    【模板】可持久化线段树
    【模板】可持久化平衡树
    【模板】左偏树
  • 原文地址:https://www.cnblogs.com/New-Godess/p/4464103.html
Copyright © 2011-2022 走看看