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

17.10.14

时间:2017-10-15 14:31:29      阅读:257      评论:0      收藏:0      [点我收藏+]

标签:cipher   als   ac自动机   节点   ring   work   clu   har   void   

  • 上午
    • BZOJ 1029 [JSOI2007]建筑抢修
    • 贪心,按t2排序后
      依次枚举建筑,尝试对其进行修理。
      如果当期建筑无法修理,
      则看之前是否有某个已经修理了的建筑的耗时大于当期建筑的耗时,
      如果有的话,则替换掉最大的那一个。
      优先队列维护

      代码:

      #include<queue>
      #include<cstdio>
      #include<cstring>
      #include<iostream>
      #include<algorithm>
      #define ll long long
      using namespace std;
      struct construction{
      	ll t1,t2;
      	bool operator <(const construction &rtm) const{
      		return t2<rtm.t2;
      	}
      }con[150005];
      ll used,cnt;
      int n;
      priority_queue<ll>q;
      int main(){
      	scanf("%d",&n);
      	for(int i=1;i<=n;i++) scanf("%lld%lld",&con[i].t1,&con[i].t2);
      	sort(con+1,con+n+1);
      	for(int i=1;i<=n;i++){
      		ll ned=con[i].t1,lim=con[i].t2;
      		if(used+ned>lim){
      			if(q.empty()) continue;
      			if(q.top()<ned) continue;
      			used=used-q.top()+ned;
      			q.pop(); q.push(ned);
      		}
      		else{
      			used=used+ned;
      			cnt++; q.push(ned);
      		}
      	}
      	printf("%lld",cnt);
      	return 0;
      }
      
    • 1030 [JSOI2007]文本生成器
    • 终于接触了AC自动机上的DP,好激动。
         
      按网上大佬的思路,我们要求的是不合法的串的个数。
      然后对模式串建trie树,构造失配指针,
      把所有不存在的边补上,避免反复沿着失配边走(---刘汝佳)
         
      接下来进行DP,对每个位置枚举填的是trie树的哪个节点,对于有结尾标记d的节点就不转移。
           
      给我的感觉是,这个getFail函数和"补边"操作呢,就是在处理DP的转移方向。

      代码:

      #include<queue>
      #include<cstdio>
      #include<cstring>
      #include<iostream>
      using namespace std;
      const int p=10007;
      char s[105];
      bool ed[60005];
      int ch[60005][30],fail[60005],sz;
      int	dp[105][6005],all=1,ans,n,m;
      int idx(char x){
      	return x-‘A‘+1;
      }
      void insert(){
      	int u=0,j=0;
      	while(s[j]!=0){
      		if(!ch[u][idx(s[j])]) ch[u][idx(s[j])]=++sz;
      		u=ch[u][idx(s[j])];
      		j++;
      	}
      	ed[u]=1;
      }
      void getFail(){
      	queue<int>q;
      	for(int c=1;c<=26;c++)if(ch[0][c])
      		q.push(ch[0][c]);
      	while(!q.empty()){
      		int u=q.front(); q.pop();
      		for(int c=1;c<=26;c++){
      			if(!ch[u][c]){
      				ch[u][c]=ch[fail[u]][c];
      				continue;
      			}
      			int v=ch[u][c];
      			fail[v]=ch[fail[u]][c];
      			if(ed[fail[v]]) ed[v]=1;
      			q.push(v);
      		}
      	}
      }
      int main(){
      	scanf("%d%d",&n,&m);
      	for(int i=1;i<=n;i++)
      		scanf("%s",s),insert();
      	for(int i=1;i<=26;i++) if(!ch[0][i])
      		ch[0][i]=++sz;
      	getFail();
      	dp[0][0]=1;
      	for(int i=1;i<=m;i++)
      		for(int j=0;j<=sz;j++){
      			if(ed[j]||!dp[i-1][j]) continue;
      			for(int k=1;k<=26;k++)
      				dp[i][ch[j][k]]=(dp[i][ch[j][k]]+dp[i-1][j])%p;
      		}
      	for(int i=1;i<=m;i++) all=all*26%p;
      	for(int j=1;j<=sz;j++) if(!ed[j]) ans=(ans+dp[m][j])%p;
      	ans=(all-ans+p)%p;
      	printf("%d\n",ans);
      	return 0;
      }
      
    • BZOJ 1031 [JSOI2007]字符加密Cipher
    • 这是一道裸的后缀数组!(以前没过,今天终于AC了)

      代码:

      #include<cstdio>
      #include<cstring>
      #include<iostream>
      #define MAXN 200005
      using namespace std;
      char s[MAXN];
      int wa[MAXN],wb[MAXN];
      int sa[MAXN],c[MAXN],n;
      bool cmp(int *y,int i,int k){
      	int aa=y[sa[i]],bb=y[sa[i-1]];
      	int cc=sa[i]+k<n?y[sa[i]+k]:-1,dd=sa[i-1]+k<n?y[sa[i-1]+k]:-1;
      	return aa==bb&&cc==dd;
      }
      void build(){
      	int m=300,*x=wa,*y=wb;
      	for(int i=0;i<m;i++) c[i]=0;
      	for(int i=0;i<n;i++) c[x[i]=s[i]]++;
      	for(int i=1;i<m;i++) c[i]+=c[i-1];
      	for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
      	for(int k=1;k<n;k<<=1){
      		int p=0;
      		for(int i=n-k;i<n;i++) y[p++]=i;
      		for(int i=0;i<n;i++) if(sa[i]>=k) y[p++]=sa[i]-k;
      		for(int i=0;i<m;i++) c[i]=0;
      		for(int i=0;i<n;i++) c[x[y[i]]]++;
      		for(int i=1;i<m;i++) c[i]+=c[i-1];
      		for(int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
      		m=1; swap(x,y); x[sa[0]]=0;
      		for(int i=1;i<n;i++)
      			x[sa[i]]=cmp(y,i,k)?m-1:m++;
      		if(m>=n) break;
      	}
      }
      int main(){
      	scanf("%s",s);
      	int N=strlen(s);
      	for(int i=0;i<N;i++) s[i+N]=s[i];
      	n=N*2; s[n]=0;
      	build();
      	for(int i=0;i<n;i++) 
      		if(sa[i]<N) printf("%c",s[sa[i]+N-1]);
      	return 0;
      }
      
    • BZOJ 1034 [ZJOI2008]泡泡堂BNB
    • 从小到大排序后
      用了一个优先队列维护之前平局的选手实力、、、
      对于从小到大枚举到的对手,
      尝试找出当前可以干掉他的最小队友,
      对于干不掉他的对友,尝试去干掉优先队列维护的平局的实力最小的对手,可以再多加一分。
         
      感觉麻烦了,网上的更简单。

      代码:

      #include<queue>
      #include<cstdio>
      #include<cstring>
      #include<iostream>
      #include<algorithm>
      using namespace std;
      int a[100005],b[100005];
      int n; 
      int work(int *A,int *B){
      	priority_queue<int,vector<int>,greater<int> >q;
      	int ans=0,i=1;
      	for(int j=1;j<=n;j++){
      		while(i<=n&&A[i]<=B[j]){
      			if(!q.empty()&&q.top()<A[i]) q.pop(),ans+=1;
      			else if(A[i]==B[j]) break; 
      			i++;
      		}
      		if(i>n) break;
      		if(A[i]==B[j]) ans+=1,q.push(B[j]);
      		else ans+=2;
      		i++;
      	}
      	return ans;
      }
      int main(){
      	scanf("%d",&n);
      	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
      	for(int i=1;i<=n;i++) scanf("%d",&b[i]);
      	sort(a+1,a+n+1);
      	sort(b+1,b+n+1);
      	int ans1=work(a,b);
      	int ans2=2*n-work(b,a);
      	printf("%d %d",ans1,ans2);
      	return 0;
      }
      
  • 下午
    • 考初赛、、、

17.10.14

标签:cipher   als   ac自动机   节点   ring   work   clu   har   void   

原文地址:http://www.cnblogs.com/zj75211/p/7670021.html

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