状态差得一批。。
考试时想写\(60\)写挂。正解就是用堆把洗衣服的和晾衣服的贪心选一遍,求出每个衣服的最短时间,然后合并时就拿最大的和最小的,次大的和次小的依次合并取\(max\)。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
const int N=100005;
typedef long long LL;
inline int rd(){
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return f?x:-x;
}
int n,m,l,w[N],d[N];
LL t1[N],t2[N],ans;
struct Node{
int id; LL w;
friend bool operator<(const Node A,const Node B){
return A.w>B.w;
}
Node(int _id=0,LL _w=0) {id=_id; w=_w;}
};
priority_queue<Node> Q;
int main(){
l=rd(),n=rd(),m=rd(); Node now;
for(int i=1;i<=n;i++) w[i]=rd(),Q.push(Node(i,1ll*w[i]));
for(int i=1;i<=l;i++){
now=Q.top(); Q.pop();
t1[i]=now.w; Q.push(Node(now.id,now.w+w[now.id]));
}
while(Q.size()) Q.pop();
for(int i=1;i<=m;i++) d[i]=rd(),Q.push(Node(i,1ll*d[i]));
for(int i=1;i<=l;i++){
now=Q.top(); Q.pop();
t2[i]=now.w; Q.push(Node(now.id,now.w+d[now.id]));
}
for(int i=1;i<=l;i++) ans=max(ans,t1[i]+t2[l-i+1]);
printf("%lld\n",ans);
return 0;
}
考场上暴搜\(20\)分。这个需要模型转化,首先说\(50\)分的做法,就是对于一个串来说,把它拆成两个,如果没有\('?'\)就拆成两个一样的,有的话拆的两个串一个把问号视作\(0\),一个视作\(1\),然后插到\(Trie\)树上。可以发现\(Trie\)树上一个节点和它的祖先不能同时存在,那么就转化成了个\(2-sat\)问题,可以暴力在树上跳,然后连边后\(2-sat\)判断,但这样连边边数过多,所以只有\(50\)分。而发现这样建边有好多无用的边,我们可以考虑优化连边,对于一个\(Trie\)上的点,我们可以把在这个点结束的串合并起来,然后建一个\(in\)和\(out\),而对于\(2-sat\)里的边,发现对于一个点来说,它要连的其实就是这个节点中除自己的其他边,可以维护一个前缀后缀点的集合,这样边的数量就便少很多。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int N=1000005;
int n,head[N],cnt,to[N<<1],nxt[N<<1],pos[N];
char s[N];
vector<int> v[N];
void add(int bg,int ed){
// cout<<bg<<" "<<ed<<endl;
to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
}
struct Trie{
int ch[N][2],fa[N],tot=1;
void build(int id){
scanf("%s",s+1); int now=1,len=strlen(s+1);
for(int i=1;i<=len;i++){
if(s[i]=='?' || s[i]=='1') {
if(ch[now][1]) now=ch[now][1];
else ch[now][1]=++tot,fa[tot]=now,now=tot;
}
else {
if(ch[now][0]) now=ch[now][0];
else ch[now][0]=++tot,fa[tot]=now,now=tot;
}
} v[now].push_back(id); pos[id]=now; now=1;
for(int i=1;i<=len;i++){
if(s[i]=='1') {
if(ch[now][1]) now=ch[now][1];
else ch[now][1]=++tot,fa[tot]=now,now=tot;
}
else {
if(ch[now][0]) now=ch[now][0];
else ch[now][0]=++tot,fa[tot]=now,now=tot;
}
}
v[now].push_back(id+n); pos[id+n]=now;
}
void solve(int id){
int now=pos[id],tmp;
while(now!=1){
for(int i=0;i<v[now].size();i++){
tmp=v[now][i];
if(tmp==id || tmp==id+n) continue;
add(id,(tmp>n?tmp-n:tmp+n));
add(tmp,(id>n?id-n:id+n));
}
now=fa[now];
}
}
}trie;
int dfn[N],low[N],num,stk[N],top,col[N],col_num;
bool vis[N];
void tarjan(int x){
dfn[x]=low[x]=++num;
stk[++top]=x; vis[x]=1;
for(int i=head[x];i;i=nxt[i]){
int u=to[i];
if(!dfn[u]) tarjan(u),low[x]=min(low[x],low[u]);
else if(vis[u]) low[x]=min(low[x],dfn[u]);
}
if(low[x]!=dfn[x]) return;
col[x]=++col_num; vis[x]=0;
while(stk[top]!=x){
vis[stk[top]]=0;
col[stk[top--]]=col_num;
} top--;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) trie.build(i);
for(int i=1;i<=2*n;i++) trie.solve(i);
for(int i=1;i<=2*n;i++) if(!dfn[i]) tarjan(i);
for(int i=1;i<=n;i++)
if(col[i]==col[i+n]) {puts("NO"); return 0;}
puts("YES");
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int N=3000005;
int n,head[N],cnt,to[N<<3],nxt[N<<3],pos[N];
char s[N];
vector<int> v[N];
void add(int bg,int ed){
to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
}
inline int work(int id) {return id<=n?id+n:id-n;}
struct Trie{
int ch[N][2],fa[N],tot=1,in[N],out[N];
void build(int id){
scanf("%s",s+1); int now=1,len=strlen(s+1);
for(int i=1;i<=len;i++){
if(s[i]=='?' || s[i]=='1') {
if(ch[now][1]) now=ch[now][1];
else ch[now][1]=++tot,fa[tot]=now,now=tot;
}
else {
if(ch[now][0]) now=ch[now][0];
else ch[now][0]=++tot,fa[tot]=now,now=tot;
}
} v[now].push_back(id); now=1;
for(int i=1;i<=len;i++){
if(s[i]=='1') {
if(ch[now][1]) now=ch[now][1];
else ch[now][1]=++tot,fa[tot]=now,now=tot;
}
else {
if(ch[now][0]) now=ch[now][0];
else ch[now][0]=++tot,fa[tot]=now,now=tot;
}
}
v[now].push_back(id+n);
}
void solve(){
int tmp=tot; tot=n+n;
for(int i=2;i<=tmp;i++){
if(v[i].size()==0) continue;
in[i]=++tot; out[i]=++tot;
for(int j=0;j<v[i].size();j++){
int x=v[i][j],y=work(v[i][j]);
for(int k=fa[i];k;k=fa[k])
if(in[k]) add(in[k],y),add(x,out[k]);
add(x,in[i]); add(out[i],y);
}
static int w[N];
for(int j=0;j<v[i].size();j++){
int x=v[i][j]; w[j]=++tot;
if(j) add(w[j],w[j-1]);
add(w[j],work(x));
int t=j-1;
if(j && work(x)==v[i][j-1]) t--;
if(t>=0) add(x,w[t]);
}
int num=v[i].size()-1;
for(int j=num;j>=0;j--){
int x=v[i][j]; w[j]=++tot;
if(j<num) add(w[j],w[j+1]);
add(w[j],work(x));
int t=j+1;
if(j<v[i].size()-1 && work(x)==v[i][j+1]) t++;
if(t<v[i].size()) add(x,w[t]);
}
}
}
}trie;
int dfn[N],low[N],num,stk[N],top,col[N],col_num;
bool vis[N];
void tarjan(int x){
dfn[x]=low[x]=++num;
stk[++top]=x; vis[x]=1;
for(int i=head[x];i;i=nxt[i]){
int u=to[i];
if(!dfn[u]) tarjan(u),low[x]=min(low[x],low[u]);
else if(vis[u]) low[x]=min(low[x],dfn[u]);
}
if(low[x]!=dfn[x]) return;
col[x]=++col_num; vis[x]=0;
while(stk[top]!=x){
vis[stk[top]]=0;
col[stk[top--]]=col_num;
} top--;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++) trie.build(i);
trie.solve();
for(int i=1;i<=trie.tot;i++) if(!dfn[i]) tarjan(i);
for(int i=1;i<=n;i++)
if(col[i]==col[i+n]) {puts("NO"); return 0;}
puts("YES");
return 0;
}
咕咕咕
原文:https://www.cnblogs.com/sdfzsyq/p/10453089.html