TJOI2015Day1测试总结
来源:互联网 发布:佛教的软件 编辑:程序博客网 时间:2024/06/11 04:44
好久没来过了。。。。
今天跟一群神犇测TJOI2015day1的题,除了我基本上都Ak了,蒟蒻的只有200分
T1:
http://www.lydsy.com/JudgeOnline/problem.php?id=3996
这题不是很难,就是一个最小割,但是由于没有深入理解矩阵的乘法,结果想了1个小时左右才发现,当Ai,Aj同时为1时才可以获得Bij,而Ai为1又得付出Ci的代价,于是就写掉了
(这题数据真心水,把B的全部加上再减掉C的就可以A了)
#include<cmath>#include<cstdio>#include<cstring>#include<cassert>#include<iostream>#include<algorithm>using namespace std;const int inf=~0u>>2,maxn=511,maxm=maxn,maxe=maxm*maxm*2;int tot=1;int now[maxm],pre[maxe],son[maxe],v[maxe];void add(int a,int b,int c){pre[++tot]=now[a]; now[a]=tot; son[tot]=b; v[tot]=c;}void cc(int a,int b,int c){add(a,b,c); add(b,a,c);}void cc1(int a,int b,int c){add(a,b,c); add(b,a,0);}int st,ed,n,ans=0,a[maxn];void init(){scanf("%d",&n); int x; st=n+1; ed=st+1; memset(a,0,sizeof(a));for (int i=1;i<=n;++i)for (int j=1;j<=n;++j)scanf("%d",&x),cc(i,j,x),a[i]+=x,a[j]+=x,ans-=x;for (int i=1;i<=n;++i) scanf("%d",&x),cc1(st,i,2*x),cc1(i,ed,a[i]); }int dep[maxm];bool bfs(){static int q[maxm]; memset(dep,0,sizeof(dep));int w=1; q[w]=st; dep[st]=1;for (int i=1;i<=w;++i) for (int p=now[q[i]];p;p=pre[p])if (v[p] && !dep[son[p]]) q[++w]=son[p],dep[q[w]]=dep[q[i]]+1;return dep[ed]>0;}int find(int x,int f){if (x==ed) return f; int ans=0;for (int p=now[x];p;p=pre[p]) if (v[p] && dep[son[p]]>dep[x]){int k=find(son[p],min(f,v[p]));v[p]-=k; v[p^1]+=k; f-=k; ans+=k;if (!f) return ans;}dep[x]=0; return ans;}int maxflow(){int ans=0;while (bfs()) ans+=find(st,inf);return ans;}void work(){printf("%d\n",-(ans+maxflow()/2));}int main(){init();work();fclose(stdin); fclose(stdout);return 0;}
T2:
http://www.lydsy.com/JudgeOnline/problem.php?id=3997
这题刚看到就YY了一个50分暴力,后来就进了第三题这个坑,最后这题就没写了
这题的话有两种做法
因为只能向下或者向右,我们设w[i*m+j]=a[i][j],h[i*m+j]=j,那么原题的就可以看成一个导弹拦截问题,w[i]代表这个位置上的导弹数,h[i]代表这个位置导弹的高度,那么
(在执行以下操作的过程中s[x]代表以x结尾的拦截还剩几个)
1、先将数量为0的导弹删掉
2、枚举每个点x
3、找到它前面第一个不比它高的最高的导弹a(找不到就到第4步),如果s[a]>=s[x],那么s[a]-=s[x](拦截完a后就拦截x),然后去第5步,否则s[x]-=s[a],把a删掉(从a出来的已经没有了),继续搞第3步
4、把答案加上s[x](表示要从x开始s[x]个拦截),去第5步
5、s[x]=w[x],然后去第2步
显然枚举每个点的时候,出了删点的过程,最多只会找到一个点,而每个点又只会被删一次,那么就是O(点数)的,但是还要找点删点,可以用个set维护,就是O(点数log点数)的,即O(n^2logn),这个已经可以过了,但是因为这题的特殊性质,可以优化到O(n^2)的,具体参见代码
还有一种很巧妙的做法,最小链覆盖=最长反链,先考虑每个格子只有0或者1,另x1<=x2的偏序关系就是(x1<x2 && y1<=y2) || x1==x2,那么反链就是x1<x2 && y1>y2,就是从右上到左下Dp一遍就行了,现在一个格子中有了多个,那么,另x1<=x2的偏序关系是(x1<x2 && y1<=y2) || (x1==x2 && y1!=y2),那么反链就是(x1<x2 && y1>y2) || (x1==x2 && y1==y2),于是惊讶的发现就是一个带权的Dp了,就O(n^2)了
前一种方法太神了没敢写,于是贴某Ak爷代码
O(n^2logn)
#include<algorithm>#include<iostream>#include<cstring>#include<cstdlib>#include<cassert>#include<cstdio>#include<cmath>#include<ctime>#include<map>using namespace std;typedef long long int64;const int maxn=1000010;int h[maxn],t[maxn];int q,sum,n,m;void init(){scanf("%d%d",&n,&m); sum=0;for(int i=1;i<=n;++i)for(int j=1;j<=m;++j){int v; scanf("%d",&v);if(v) ++sum,h[sum]=j,t[sum]=v;}}typedef multimap<int,int>::iterator iter;multimap<int,int> s; int f[maxn];void solve(){int64 ans=0; s.clear();memset(f,0,sizeof(f));for(int i=1;i<=sum;++i){for(iter x;f[i]<t[i];){x=s.upper_bound(h[i]); if(x==s.begin()) break;--x; int k=min(f[x->second],t[i]-f[i]);f[x->second]-=k,f[i]+=k;if(!f[x->second]) s.erase(x);}if(f[i]<t[i]) ans+=t[i]-f[i],f[i]=t[i];s.insert(make_pair(h[i],i));}cout<<ans<<endl;}int main(){for(scanf("%d",&q);q--;){init();solve();}return 0;}
优化后变成了O(n^2) orz
#include<algorithm>#include<iostream>#include<cstring>#include<cstdlib>#include<cassert>#include<cstdio>#include<cmath>#include<ctime>#include<map>using namespace std;const int maxbuf=20000000;char buf[maxbuf],*wbuf=buf;inline int getint(){int x=0; for(;!isdigit(*wbuf);++wbuf);while(isdigit(*wbuf)) x=x*10+*wbuf++-'0'; return x;}typedef long long int64;const int maxn=1010;int64 f[maxn],g[maxn];int q,n,m;int main(){fread(buf,1,maxbuf,stdin);for(int q=getint();q--;){n=getint(),m=getint();memset(f,0,sizeof(f)); int64 ans=0;for(int i=1;i<=n;++i){int64 sum=0;memset(g,0,sizeof(g));for(int j=1;j<=m;++j){int v=getint(); sum+=f[j];if(f[j]>v) continue;g[j]=min(sum,v-f[j]);if(v>sum) ans+=v-sum,sum=v;f[j]=v;}for(int j=m,k=m-1;j>=1;--j){if(k>=j) k=j-1;for(;k;--k){int64 v=min(g[j],f[k]);g[j]-=v,f[k]-=v;if(!g[j]) break;}}}cout<<ans<<endl;}return 0;}
第二种方法
#include<cmath>#include<cstdio>#include<cstring>#include<cassert>#include<iostream>#include<algorithm>using namespace std;const int maxn=1011,maxbuf=20000000;char buf[maxbuf],*wbuf=buf;inline void read(int &x){x=0; while (!isdigit(*wbuf)) ++wbuf;while (isdigit(*wbuf)) x=x*10+*wbuf++-'0';}int a[maxn][maxn],f[maxn][maxn],n,m;void init(){read(n); read(m);for (int i=1;i<=n;++i) for (int j=1;j<=m;++j)read(a[i][j]);}void work(){for (int i=1;i<=m;++i) f[0][i]=0;for (int i=1;i<=n;++i) f[i][m+1]=0;for (int i=1;i<=n;++i) for (int j=m;j>=1;--j)f[i][j]=max(max(f[i-1][j+1]+a[i][j],f[i-1][j]),f[i][j+1]);cout<<f[n][1]<<endl;}int main(){fread(buf,1,maxbuf,stdin);int T; read(T);while (T--) init(),work();return 0;}
T3:
http://www.lydsy.com/JudgeOnline/problem.php?id=3998
这题要求有关子串,就知道是后缀自动机,但是因为太弱了,后缀自动机写不出啊,于是就傻叉的写了后缀数组,虽然测试A掉了,但是bzoj交到死也TLE(某大神硬是DC3搞过去了orz)
先来讲一下后缀数组的写法吧,对于T=0的就是个论文题,来讲讲T=1的情况
首先按照后缀的排序枚举每个后缀
看这个后缀在所有子串中的排名,如果<rank就继续枚举,如果>=rank就二分一下在什么位置
统计的时候,要注意把下面与其相同的部分也统计掉,然后乱二分几下,就变成了O(nlogn)的了
后缀自动机果然还是得写啊。。。
死都TLE的
#include<cmath>#include<ctime>#include<cstdio>#include<cstring>#include<cassert>#include<iostream>#include<algorithm>#define min(a,b) ((a)<(b)?(a):(b))using namespace std;const int maxn=500011;typedef long long LL;char s[maxn]; int op,rk,n;void init(){scanf("%s%d%d",s,&op,&rk); n=strlen(s)+1;}int sa[maxn],rank[maxn],height[maxn];inline bool cmp(int *x,int a,int b,int len){return x[a]==x[b] && x[a+len]==x[b+len];}void suffix_sort(){static int wx[maxn],ws[maxn],wy[maxn]; int i,m=300,*x=wx,*y=wy;for (i=0;i<m;++i) ws[i]=0;for (i=0;i<n;++i) ++ws[x[i]=s[i]];for (i=1;i<m;++i) ws[i]+=ws[i-1];for (i=n-1;i>=0;--i) sa[--ws[x[i]]]=i;for (int len=1,p=0;p<n;len<<=1,m=p){for (p=0,i=n-len;i<n;++i) y[p++]=i;for (i=0;i<n;++i) if (sa[i]>=len) y[p++]=sa[i]-len;for (i=0;i<m;++i) ws[i]=0;for (i=0;i<n;++i) ++ws[x[y[i]]];for (i=1;i<m;++i) ws[i]+=ws[i-1];for (i=n-1;i>=0;--i) sa[--ws[x[y[i]]]]=y[i];for (swap(x,y),x[sa[0]]=0,i=p=1;i<n;++i) // y is rankx[sa[i]]=cmp(y,sa[i-1],sa[i],len)?p-1:p++;}for (int i=0;i<n;++i) rank[i]=x[i];}void get_height(){for (int i=0,j,len=0;i<n-1;height[rank[i++]]=len)for (len?--len:0,j=sa[rank[i]-1];s[i+len]==s[j+len];++len);}int rmq[maxn][22],lg2[maxn];void RMQ(){lg2[1]=0; for (int i=2;i<=n;++i) lg2[i]=lg2[i>>1]+1;for (int i=n-1;i>=1;--i){rmq[i][0]=height[i]; int x=lg2[n-i];for (int j=1;j<=x;++j)rmq[i][j]=min(rmq[i][j-1],rmq[i+(1<<(j-1))][j-1]);}}int Rget(int a,int b){int x=lg2[b-a+1];return min(rmq[a][x],rmq[b-(1<<x)+1][x]);}void prepare(){suffix_sort(); get_height(); RMQ();}LL f[maxn];LL Query(int s,int x){if (s==height[x]) return f[x];int t=x+1,w=n;while (t<=w){int mid=(t+w)>>1;if (Rget(x+1,mid)<s) w=mid-1;else t=mid+1;}++w; return (LL)s*(w-x)+f[w];}LL Query2(int s,int x){int t=x,w=n;while (t<=w){int mid=(t+w)>>1;if (Rget(x,mid)<s) w=mid-1;else t=mid+1;}++w; return (LL)s*(w-x)+f[w];}void write(int a,int len){for (int i=0;i<len;++i) putchar(s[a+i]); putchar('\n');}void work(){prepare(); --n;if (!op){for (int i=1;i<=n;++i){int sum=n-sa[i]-height[i];if (rk>sum) rk-=sum;else{write(sa[i],height[i]+rk); return;}}puts("-1"); return;}f[n+1]=0;for (int i=n;i>=1;--i){f[i]=Query2(height[i],i+1)+height[i];}for (int i=1;i<=n;++i){int len=n-sa[i]; LL tmp=f[i],res=Query(len,i)-tmp;if (rk>res) rk-=res;else{int t=height[i]+1,w=len;while (t<=w){int mid=(t+w)>>1;if (Query(mid,i)-tmp>=rk) w=mid-1;else t=mid+1;}write(sa[i],w+1); return;}}puts("-1"); return;}int main(){freopen("string.in","r",stdin);freopen("string.out","w",stdout);init();work();fclose(stdin); fclose(stdout);return 0;}
DC3的 orz
#include<bits/stdc++.h>using namespace std;#define X first#define Y second#define mp make_pair#define ph push#define pb push_back#define REP(i,a,n) for(int _tmp=n,i=a;i<=_tmp;++i)#define DEP(i,a,n) for(int _tmp=n,i=a;i>=_tmp;--i)#define rep(i,a,n) for(int i=(a);i<=(n);++i)#define dep(i,a,n) for(int i=(a);i>=(n);--i)#define ALL(x,S) for(__typeof((S).end()) x=S.begin();x!=S.end();x++)#define eps 1e-8#define pi 3.1415926535897#define sqr(x) ((x)*(x))#define MAX(a,b) a=max(a,b)#define MIN(a,b) a=min(a,b)#define SZ(x) ((int)(x).size())#define CPY(a,b) memcpy(a,b,sizeof(a))#define CLR(a) memset(a,0,sizeof(a))#define POSIN(x,y) (1<=(x)&&(x)<=n&&1<=(y)&&(y)<=m)#define all(x) (x).begin(),(x).end()#define COUT(S,x) cout<<fixed<<setprecision(x)<<S<<endltypedef long long ll;typedef double lf;typedef pair<int,int> pii;typedef pair<ll,ll> pll;typedef pair<lf,lf> pff;typedef complex<double> CD;const int inf=0x20202020;const int mod=1000000007;template<class T> inline void read(T&x){bool fu=0;char c;for(c=getchar();c<=32;c=getchar());if(c=='-')fu=1,c=getchar();for(x=0;c>32;c=getchar())x=x*10+c-'0';if(fu)x=-x;};template<class T> inline void read(T&x,T&y){read(x);read(y);}template<class T> inline void read(T&x,T&y,T&z){read(x);read(y);read(z);}template<class T> inline void read(T&x,T&y,T&z,T&q){read(x);read(y);read(z);read(q);}const int DX[]={1,0,-1,0},DY[]={0,1,0,-1};ll powmod(ll a,ll b) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}ll powmod(ll a,ll b,ll mod) {ll res=1;a%=mod;for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}//*******************************************#define rank orzlydconst int N=511111,M=111111;int l,m,n,C;char s[N],asks[N];int rank[N],rank2[N],pai[N],sa[N],rmq[22][N],height[N];ll h[N],x,y,hh[N];/*namespace SA{int *x=rank,*y=rank2,*t;bool cmp(int *y,int a1,int a2, int a3){return y[a1]==y[a2]&&y[a1+a3]==y[a2+a3];}bool scmp(const int &a, const int &b){return x[a]<x[b];}void calcsa(){ int j=1,p=1,m=20010; rep(i,1,n) pai[i]=i,x[i]=s[i]; sort(pai+1,pai+n+1,scmp); rep(i,1,n) sa[i]=pai[i+1]; for(;j<=n;j*=2,m=p){ p=1;rep(i,n-j,n-1) y[p++]=i; rep(i,1,n) if(sa[i]>j) y[p++]=sa[i]-j; rep(i,1,m) pai[i]=0; rep(i,1,n) ++pai[x[y[i]]]; rep(i,2,m) pai[i]+=pai[i-1]; dep(i,n,1) sa[pai[x[y[i]]]--]=y[i]; t=x;x=y;y=t;p=2;x[sa[1]]=1; rep(i,2,n) x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++; }}void calch(){ int i,j,k=0;rep(i,0,n) rank[sa[i]]=i; for(i=1;i<=n;h[rank[i++]]=k) for(k?k--:0,j=sa[rank[i]-1];s[i+k]==s[j+k];k++);}}*/namespace SAA{void init(){ int *x = rank, *y = height; static int w[N]; for (int i = 1; i <= n; ++i) ++w[x[i] = s[i] - 96]; for (int i = 2; i <= 126; ++i) w[i] += w[i - 1]; for (int i = 1; i <= n; ++i) sa[w[x[i]]--] = i; for (int k = 1, m = 126; k < n; k <<= 1, swap(x, y)) { int t = 0; for (int i = n - k + 1; i <= n; ++i) y[++t] = i; for (int i = 1; i <= n; ++i) if (sa[i] - k >= 1) y[++t] = sa[i] - k; memset(w + 1, 0, m << 2); for (int i = 1; i <= n; ++i) ++w[x[i]]; for (int i = 2; i <= m; ++i) w[i] += w[i - 1]; for (int i = n; i; --i) sa[w[x[y[i]]]--] = y[i]; m = 0; for (int i = 1; i <= n; ++i) { int u = sa[i], v = sa[i - 1]; y[u] = i == 1 || x[u] != x[v] || x[u + k] != x[v + k] ? ++m : m; } if (m == n) break; } if (y != rank) memcpy(rank + 1, y + 1, n << 2); for (int i = 1, h = 0; i <= n; ++i) { if (h) --h; int j = sa[rank[i] - 1]; while (s[i + h] == s[j + h]) ++h; height[rank[i]] = h; }}}int LOG[N];inline int RMQ(const int &l,const int &r){ if(l>r)return inf; int p=LOG[r-l+1]; return min(rmq[p][l],rmq[p][r-(1<<p)+1]);}ll ta[N],tb[N],tp;int main(){ //ios::sync_with_stdio(false); freopen("string.in","r",stdin);freopen("string.out","w",stdout); rep(i,1,20)LOG[1<<i]=i; rep(i,2,500000)if(!LOG[i])LOG[i]=LOG[i-1]; for(s[1]=getchar();s[1]<'a'||s[1]>'z';s[1]=getchar());n=1; for(;s[n]>='a'&&s[n]<='z';s[++n]=getchar());s[n]=0;--n; //printf("%d %s\n",n,s+1); //SA::calcsa();SA::calch(); SAA::init();rep(i,1,n)h[i]=height[i]; //rep(i,1,n)printf("%d %d %lld\n",i,sa[i],h[i]); ++n; rep(i,1,n)rmq[0][i]=h[i]; rep(i,1,20)rep(j,1,n){ if(j+(1<<i-1)>n)break; rmq[i][j]=min(rmq[i-1][j],rmq[i-1][j+(1<<i-1)]); } //return 0; //printf("%d\n",clock()); read(x,y); if(x==0){ h[0]=0; rep(i,1,n)h[i]=h[i-1]+(n-sa[i])-h[i]; int Min=1,Max=n,pt,len; while(Min<Max){ int mid=Min+Max>>1;if(h[mid]<y)Min=mid+1;else Max=mid; } if(Min==n){puts("-1");return 0;} pt=Min;len=y-h[pt-1]+rmq[0][pt]-1;pt=sa[Min]; rep(i,pt,pt+len)putchar(s[i]);puts(""); }else{ if(y>n*(n-1)/2){puts("-1");return 0;} ll res=0;tp=0; dep(i,n,1){ while(tp&&h[ta[tp]]>=h[i])--tp;ta[++tp]=i;tb[tp]=hh[i-1]=tb[tp-1]+(ta[tp-1]-i)*h[i]; } //rep(i,1,n)printf("%d %d %lld %lld\n",i,sa[i],h[i],hh[i]); ll sum=0; rep(i,1,n){ sum+=(n-sa[i]);if(sum+hh[i]>=y){ int pos; dep(j,n-sa[i],1){ int Min=i,Max=n,pt,len; while(Min<Max){ int mid=Min+Max+1>>1;if(RMQ(i+1,mid)>=j)Min=mid;else Max=mid-1; } //printf("%d-%d\n",j,Min); y+=Min-i+1; if(sum+hh[i]<y){pos=j;break;} } rep(j,sa[i],sa[i]+pos-1)putchar(s[j]); //printf("%d %d\n",i,pos); break; } } } //printf("\n%d\n",clock()); return 0;}
自动机的
#include<cmath>#include<cstdio>#include<cstring>#include<cassert>#include<iostream>#include<algorithm>using namespace std;typedef long long LL;const int maxn=500011;char s[maxn]; int op,rank;void init(){scanf("%s%d%d",s,&op,&rank);}struct Tsam{struct node{node *ch[26],*f; int ml,s,sz; LL sum;int get(int op){return op?sum:sz;}void clear(){memset(ch,0,sizeof(ch)); f=0; ml=s=0; sz=1; sum=0;}}e[maxn<<1],*root,*last;int tot;node *newnode(){e[tot].clear(); return &e[tot++];}void clear(){tot=0; last=root=newnode();}void ins(int c){node *np=newnode(),*p=last; np->ml=p->ml+1; np->s=1;for (last=np;p && !p->ch[c];p=p->f) p->ch[c]=np;if (!p) {np->f=root; return;} node *q=p->ch[c];if (p->ml+1==q->ml){np->f=q; return;}node *r=newnode(); *r=*q; r->ml=p->ml+1; r->s=0;for (np->f=q->f=r;p && p->ch[c]==q;p=p->f) p->ch[c]=r;}void Dp(){static node *q[maxn<<1]; q[1]=root;static int ws[maxn<<1]; memset(ws,0,sizeof(ws));for (int i=0;i<tot;++i) ++ws[e[i].ml];for (int i=1;i<=tot;++i) ws[i]+=ws[i-1];for (int i=0;i<tot;++i) q[ws[e[i].ml]--]=e+i;for (int i=tot;i>=1;--i){q[i]->sum+=q[i]->s;for (int c=0;c<26;++c) if (q[i]->ch[c])q[i]->sz+=q[i]->ch[c]->sz,q[i]->sum+=q[i]->ch[c]->sum;if (q[i]->f) q[i]->f->s+=q[i]->s;}}void getans(int op,int rank){Dp(); rank+=op?root->s:1;if (root->get(op)<rank){puts("-1"); return;}for (node *p=root;;){rank-=op?p->s:1; if (!rank) return;for (int c=0;c<26;++c) if (p->ch[c]){int tmp=p->ch[c]->get(op);if (tmp<rank) rank-=tmp;else {putchar('a'+c); p=p->ch[c]; break;}}}}}sam;void work(){sam.clear(); for (int i=0;s[i];++i) sam.ins(s[i]-'a');sam.getans(op,rank);}int main(){init();work();return 0;}
在看到第一题的时候,没有很快想出模型,第二题也是根本没有想到Dilworth定理(导弹拦截的模型转化也没想到),第三题虽然过了,但是改了太久,主要是因为把数组的意义搞混乱了,以后要注意数组的真实含义
- TJOI2015Day1测试总结
- 测试总结
- 测试总结
- 测试总结
- 测试总结
- 测试总结
- 总结测试
- 测试总结
- 测试总结
- 测试总结
- 测试基础---测试总结
- 【系统测试】性能测试总结
- 性能测试总结---测试流程
- 【总结】软件测试基础总结
- [软件]测试要点总结
- GUI测试总结
- 回归测试总结
- GUI测试总结
- devstack多节点时间不一致导致服务无法up
- noip 2004 合并果子
- ubuntu14.04中的tmp文件夹生命周期
- Java学习路线图·影响一代又一代程序员的经典书籍!
- java选择排序
- TJOI2015Day1测试总结
- nginx源码学习——命令行选项处理
- OC和Swift混编(惊喜!)
- 登录、注册页面及后台代码
- java基础——java中的异常
- c++中BOOL和bool的区别
- Android实现网络多线程断点续传下载
- JavaScript Notes 1
- 算法导论 15章 动态规划