2012杭州网络赛赛后【缺ACDI】

A  Boomerang (HDU 4410)

B  Arrest (HDU 4411)


最小费用流,建-inf边保证n个点都被访问到

 #include<cstdio>
 #include<cstring>
 #include<algorithm>
 using namespace std;
 
 const int N=222,M=111111;
 
 const int inf=0x3f3f3f3f;
 
 MinCostMaxFlow mc;
 
 int d[N][N];
 int main()
 {
     //freopen("in.txt","r",stdin);
     int n,m,k;
     while(scanf("%d%d%d",&n,&m,&k),n||m||k)
     {
         int s=0,ss=n*2+1,t=n*2+2;
         memset(d,63,sizeof(d));
         for(int i=0;i<m;i++)
         {
             int x,y,len;
             scanf("%d%d%d",&x,&y,&len);
             d[x][y]=d[y][x]=min(d[x][y],len);
         }
         for(int k=0;k<=n;k++) for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
         mc.init();
         mc.addedge(s,ss,k,0);
         for(int i=1;i<=n;i++) mc.addedge(ss,i,1,d[i][0]);
         for(int i=1;i<=n;i++) mc.addedge(i,i+n,1,-0xfffff);
         for(int i=1;i<=n;i++) for(int j=i+1;j<=n;j++) mc.addedge(i+n,j,1,d[i][j]);
         for(int i=1;i<=n;i++) mc.addedge(i+n,t,1,d[i][0]);
         mc.addedge(ss,t,k,0);
         int f,c;
         mc.mincost(s,t,n*2+3,f,c);
         printf("%d\n",c+0xfffff*n);
     }
     return 0;
 }


C  Sky Soldiers (HDU 4412)


D  Logical Expression (HDU 4413)


E  Finding crosses (HDU 4414)


n^3四个方向搜最长

 #include<cstdio>
 
 char s[100][100];
 int main()
 {
     //freopen("in","r",stdin);
     int n;
     while(scanf("%d",&n),n)
     {
         for(int i=0;i<n;i++) scanf("%s",s[i]);
         int ans=0;
         for(int x=1;x<n-1;x++) for(int y=1;y<n-1;y++)
         {
             if(s[x][y]!='#') continue;
             int up=0,down=0,left=0,right=0,fg=1;
 
             for(int i=x-1;i>=0;i--)
             {
                 if(s[i][y]!='#') break;
                 up++;
                 if(s[i][y+1]=='#'||s[i][y-1]=='#') fg=0;
             }
 
             for(int i=x+1;i<n;i++)
             {
                 if(s[i][y]!='#') break;
                 down++;
                 if(s[i][y+1]=='#'||s[i][y-1]=='#') fg=0;
             }
 
             for(int i=y-1;i>=0;i--)
             {
                 if(s[x][i]!='#') break;
                 left++;
                 if(s[x-1][i]=='#'||s[x+1][i]=='#') fg=0;
             }
 
             for(int i=y+1;i<n;i++)
             {
                 if(s[x][i]!='#') break;
                 right++;
                 if(s[x-1][i]=='#'||s[x+1][i]=='#') fg=0;
             }
 
             if(fg&&up==down&&down==left&&left==right&&up) ans++;
         }
         printf("%d\n",ans);
     }
     return 0;
 }


F  Assassin’s Creed (HDU 4415)


贪心 若可能则先杀了bi非0且ai最小的那个,然后算出所有bi.second之和为cnt,杀cnt个ai最大的。再用自己的刀杀ai尽量小的剩余人

 #include <cstdio>
 #include <algorithm>
 using namespace std;
 
 const int N=100010;
 pair<int,int>a[N];
 
 int main()
 {
     int n,m,t,cas=1;
     scanf("%d",&t);
     while(t--)
     {
         scanf("%d%d",&n,&m);
         for(int i=0;i<n;i++) scanf("%d%d",&a[i].first,&a[i].second);
         sort(a,a+n);
         int cst=0,cnt=0,id;
         for(int i=0;i<n;i++) if(a[i].second){ id=i;break;}
         if(m<a[id].first) id=-1;
         else{
             cst=a[id].first,cnt=1;
             for(int i=0;i<n;i++) cnt+=a[i].second;
         }
         if(cnt>n) cnt=n;
         for(int i=0;i<n&&cnt<n&&a[i].first+cst<=m;i++) if(i!=id) cst+=a[i].first,cnt++;
         printf("Case %d: %d %d\n",cas++,cnt,cst);
     }
     return 0;
 }

G  Good Article Good sentence (HDU 4416)


后缀数组,ans=总数-重复。s的每一个后缀与非s中串的lcp为对应重复子串个数。s串自身重复则只保留第一个串的cnt不变,其他视为重复删去。

可以利用性质lcp(i,j)=min(height[k]){i<k<=j},正反分别扫一遍求出cnt[k]=min(min(height[w]){i<w<=k},height[w]{k<w<=j})。

 #include<cstdio>
 #include<cstring>
 #include<algorithm>
 using namespace std;
 
 const int N=100010*3;
 const int inf=0x3f3f3f3f;
 
 int ua[N],ub[N],us[N];
 int cmp(int *r,int a,int b,int l){return r[a]==r[b]&&r[a+l]==r[b+l];}
 
 void da(int *r,int *sa,int n,int m)
 {
     int i,j,p,*x=ua,*y=ub,*t;
     for(i=0;i<m;i++) us[i]=0;
     for(i=0;i<n;i++) us[x[i]=r[i]]++;
     for(i=1;i<m;i++) us[i]+=us[i-1];
     for(i=n-1;i>=0;i--) sa[--us[x[i]]]=i;
     for(j=1,p=1;p<n;j*=2,m=p)
     {
         for(p=0,i=n-j;i<n;i++) y[p++]=i;
         for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
         for(i=0;i<m;i++) us[i]=0;
         for(i=0;i<n;i++) us[x[i]]++;
         for(i=1;i<m;i++) us[i]+=us[i-1];
         for(i=n-1;i>=0;i--) sa[--us[x[y[i]]]]=y[i];
         for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
             x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
     }
 }
 int rank[N],hei[N];
 void calhei(int *r,int *sa,int n)
 {
     int i,j,k=0;
     for(i=1;i<=n;i++) rank[sa[i]]=i;
     for(i=0;i<n;hei[rank[i++]]=k)
         for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
 }
 
 char s[N];
 int r[N],sa[N],cnt[N];
 int main()
 {
     int t,n,cas=1;
     scanf("%d",&t);
     while(t--)
     {
         scanf("%d%s",&n,s);
         int len=strlen(s),m=0,k=28;
         for(int i=0;i<len;i++) r[m++]=s[i]-96;
         for(int i=0;i<n;i++)
         {
             r[m++]=k++;
             scanf("%s",s);
             for(int j=0;s[j];j++) r[m++]=s[j]-96;
         }
         r[m]=0;
         da(r,sa,m+1,k);
         calhei(r,sa,m);
         memset(cnt,0,sizeof(cnt));
         int lcp=inf;
         for(int i=1;i<=m;i++)
         {
             if(sa[i]<len)
             {
                 lcp=min(lcp,hei[i]);
                 cnt[sa[i]]=max(lcp,cnt[sa[i]]);
             }
             else lcp=inf;
         }
         lcp=inf;
         for(int i=m;i;i--)
         {
             if(sa[i-1]<len)
             {
                 lcp=min(lcp,hei[i]);
                 cnt[sa[i-1]]=max(lcp,cnt[sa[i-1]]);
             }
             else lcp=inf;
         }
         for(int i=1;i<=m;i++) if(sa[i]<len&&sa[i-1]<len) cnt[sa[i-1]]=max(cnt[sa[i-1]],hei[i]);
         long long ans=(long long)len*(len+1)/2;
         for(int i=0;i<len;i++) ans-=cnt[i];
         printf("Case %d: %I64d\n",cas++,ans);
     }
     return 0;
 }

H  Super Mario (HDU 4417)


离散化+树状数组 在树状数组中对应插入删除的数离散化后的位置加1或减1,求sum(hz[k])即为比它小的数的个数。区间询问则计算ans[r]-ans[l-1]即可。

此题亦可用划分树+二分答案。

 #include<map>
 #include<cstdio>
 #include<cstring>
 #include<algorithm>
 using namespace std;
 
 const int N=100010;
 const int inf=0x3f3f3f3f;
 int bin[N],num[N],arr[N];
 
 struct Query
 {
     int l,r,h,i,ans;
     void init(int i){scanf("%d%d%d",&l,&r,&h);ans=0;this->i=i;l--;}
 }q[N];
 bool cmp1(Query a,Query b){return a.l<b.l;}
 bool cmp2(Query a,Query b){return a.r<b.r;}
 bool cmp3(Query a,Query b){return a.i<b.i;}
 
 void init(){memset(arr,0,sizeof(arr));}
 void add(int k,int v){while(k<N) arr[k]+=v,k+=k&-k;}
 int sum(int k){int ans=0;while(k) ans+=arr[k],k-=k&-k;return ans;}
 
 int main()
 {
     //freopen("in.txt","r",stdin);
     int t,n,m,cas=1;
     scanf("%d",&t);
     while(t--)
     {
         scanf("%d%d",&n,&m);
         for(int i=0;i<n;i++) scanf("%d",num+i),bin[i]=num[i];
         for(int i=0;i<m;i++) q[i].init(i);
         printf("Case %d:\n",cas++);
 
         bin[n]=inf;
         sort(bin,bin+n+1);
         map<int,int>hz;
         int len=unique(bin,bin+n+1)-bin;
         for(int i=0;i<len;i++) hz[bin[i]]=i+1;
 
         sort(q,q+m,cmp1);init();
         for(int i=0,j=0;i<=n;i++)
         {
             while(j<m&&q[j].l<i) q[j].ans-=sum(upper_bound(bin,bin+len,q[j].h)-bin),j++;
             if(i==n) break;
             add(hz[num[i]],1);
         }
 
         sort(q,q+m,cmp2);init();
         for(int i=0,j=0;i<=n;i++)
         {
             while(j<m&&q[j].r<i) q[j].ans+=sum(upper_bound(bin,bin+len,q[j].h)-bin),j++;
             if(i==n) break;
             add(hz[num[i]],1);
         }
 
         sort(q,q+m,cmp3);
         for(int i=0;i<m;i++) printf("%d\n",q[i].ans);
     }
     return 0;
 }


I  Time travel (HDU 4418)


J  Colourful Rectangle (HDU 4419)


矩形面积并(模板)+容斥关系

 #include<cstdio>
 #include<cstring>
 #include<algorithm>
 using namespace std;
 
 const int N=100010*2;
 typedef long long ll;
 typedef ll type;
 type bin[N];
 
 struct line
 {
     type x,y0,y1;
     int d;
     line(){}
     line(type x,type y0,type y1,int d):x(x),y0(y0),y1(y1),d(d){}
     bool operator < (const line &u) const
     {
         if(x!=u.x) return x<u.x;
         return d>u.d;
     }
 }lin[N];
 
 struct node
 {
     int l,r,c;
     type m;
     int mid(){return (l+r)>>1;}
     void update(int);
 }tree[N*4];
 
 void node::update(int rt)
 {
     if(c) m=bin[r]-bin[l];
     else if(l+1==r) m=0;
     else m=tree[rt<<1].m+tree[rt<<1|1].m;
 }
 
 void build(int rt,int l,int r)
 {
     tree[rt].l=l;tree[rt].r=r;
     tree[rt].c=0;tree[rt].m=0;
     if(l+1==r) return;
     int mid=(l+r)>>1;
     build(rt<<1,l,mid);
     build(rt<<1|1,mid,r);
 }
 
 void insert(int rt,int l,int r,int d)
 {
     if(l<=tree[rt].l&&tree[rt].r<=r)
     {
         tree[rt].c+=d;
         tree[rt].update(rt);
         return;
     }
     int mid=tree[rt].mid();
     if(l<mid) insert(rt<<1,l,r,d);
     if(mid<r) insert(rt<<1|1,l,r,d);
     tree[rt].update(rt);
 }
 struct Rect
 {
     int n,x0[N],x1[N],y0[N],y1[N];
     ll ans;
     void init(){n=ans=0;}
     void insert(int a,int b,int c,int d){x0[n]=a,y0[n]=b,x1[n]=c,y1[n++]=d;}
 }rect[8];
 
 ll solve(Rect &r)
 {
     if(r.n==0) return 0;
     if(r.n==1) return ll(r.x1[0]-r.x0[0])*(r.y1[0]-r.y0[0]);
     int tot=0,n=r.n;
     for(int i=0;i<n;i++)
     {
         bin[tot]=r.y0[i];lin[tot++]=line(r.x0[i],r.y0[i],r.y1[i], 1);
         bin[tot]=r.y1[i];lin[tot++]=line(r.x1[i],r.y0[i],r.y1[i],-1);
     }
     sort(lin,lin+tot);
     sort(bin,bin+tot);
     tot=unique(bin,bin+tot)-bin;
     build(1,0,tot-1);
     ll ans=0;
     for(int i=0;i<n*2;i++)
     {
         int lft=lower_bound(bin,bin+tot,lin[i].y0)-bin;
         int rht=lower_bound(bin,bin+tot,lin[i].y1)-bin;
         if(lft!=rht) insert(1,lft,rht,lin[i].d);
         ans+=tree[1].m*(lin[i+1].x-lin[i].x);
     }
     return ans;
 }
 
 int main()
 {
     int n,t,cas=1;
     scanf("%d",&t);
     while(t--)
     {
         scanf("%d",&n);
         char op[2];
         for(int i=0;i<8;i++) rect[i].init();
         for(int i=0; i<n; i++)
         {
             int a,b,c,d;
             scanf("%s%d%d%d%d",op,&a,&b,&c,&d);
             if(op[0]=='R') for(int i=0;i<8;i++) if(i&4) rect[i].insert(a,b,c,d);
             if(op[0]=='G') for(int i=0;i<8;i++) if(i&2) rect[i].insert(a,b,c,d);
             if(op[0]=='B') for(int i=0;i<8;i++) if(i&1) rect[i].insert(a,b,c,d);
         }
         ll ans[8];
         for(int i=0;i<8;i++) ans[i]=solve(rect[i]);
         ll rgb=ans[1]+ans[2]+ans[4]-ans[3]-ans[5]-ans[6]+ans[7];
         printf("Case %d:\n",cas++);
         printf("%I64d\n",ans[7]-ans[3]);
         printf("%I64d\n",ans[7]-ans[5]);
         printf("%I64d\n",ans[7]-ans[6]);
         printf("%I64d\n",ans[4]+ans[2]-ans[6]-rgb);
         printf("%I64d\n",ans[4]+ans[1]-ans[5]-rgb);
         printf("%I64d\n",ans[2]+ans[1]-ans[3]-rgb);
         printf("%I64d\n",rgb);
     }
     return 0;
 }




  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值