大都是经典的套路题,下面我没做太多详细的叙述,不懂的留言就可以。
A:暴力跑一遍就可以了
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+10;
int neg[maxn],pos[maxn];
int main()
{
int n,k,t;
while(cin>>n>>k)
{
bool ans=true;
memset(neg,0,sizeof(neg));
memset(pos,0,sizeof(pos));
for(int m=1;m<=k;m++)
{
bool flag=false;
cin>>n;
while(n--)
{
cin>>t;
if(t<0)
{
if(pos[-t]==m) flag=true;
else neg[-t]=m;
}
else if(neg[t]==m) flag=true;
else pos[t]=m;
}
if(!flag) ans=false;
}
if(!ans) puts("YES");
else puts("NO");
}
}
B: 水题,每一行如果出现x,就必须有-x,bool数组判一下就过了。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e4+10;
int neg[maxn],pos[maxn];
int main()
{
int n,k,t;
while(cin>>n>>k)
{
bool ans=true;
memset(neg,0,sizeof(neg));
memset(pos,0,sizeof(pos));
for(int m=1;m<=k;m++)
{
bool flag=false;
cin>>n;
while(n--)
{
cin>>t;
if(t<0)
{
if(pos[-t]==m) flag=true;
else neg[-t]=m;
}
else if(neg[t]==m) flag=true;
else pos[t]=m;
}
if(!flag) ans=false;
}
if(!ans) puts("YES");
else puts("NO");
}
}
C: 简单的博弈,广搜一下,把能确定胜负的点放进队列,最后不能确定胜负的就是平局
#include<bits/stdc++.h>
using namespace std;
struct Node
{
int p;
bool ifwin;
bool flag;
Node(int _p=0,bool _ifwin=0,bool _flag=0):p(_p),ifwin(_ifwin),flag(_flag){}
};
const int maxn=1e4+10;
int a,b;
int astep[maxn],bstep[maxn];
int apd[maxn],bpd[maxn];
int acnt[maxn],bcnt[maxn];
int main()
{
int n,step;
while(~scanf("%d",&n))
{
memset(acnt,0,sizeof(acnt));
memset(bcnt,0,sizeof(bcnt));
memset(apd,-1,sizeof(apd));
memset(bpd,-1,sizeof(bpd));
scanf("%d",&a);
for(int i=0;i<a;i++) scanf("%d",&step),astep[i]=step;
scanf("%d",&b);
for(int i=0;i<b;i++) scanf("%d",&step),bstep[i]=step;
queue<Node>Q;
apd[0]=bpd[0]=0;
Q.push(Node(0,0,1));
Q.push(Node(0,0,0));
while(!Q.empty())
{
Node head=Q.front();
Q.pop();
if(head.flag)
{
for(int i=0;i<b;i++)
{
int lst=((head.p-bstep[i])%n+n)%n;
if(~bpd[lst]) continue;
if(!head.ifwin)
{
bpd[lst]=1;
Q.push(Node(lst,1,!head.flag));
continue;
}
else bcnt[lst]++;
if(bcnt[lst]==b)
{
bpd[lst]=0;
Q.push(Node(lst,0,!head.flag));
}
}
}
else
{
for(int i=0;i<a;i++)
{
int lst=((head.p-astep[i])%n+n)%n;
if(~apd[lst]) continue;
if(!head.ifwin)
{
apd[lst]=1;
Q.push(Node(lst,1,!head.flag));
continue;
}
else acnt[lst]++;
if(acnt[lst]==a)
{
apd[lst]=0;
Q.push(Node(lst,0,!head.flag));
}
}
}
}
for(int i=1;i<n;i++)
{
if(i>1) printf(" ");
if(apd[i]==1) printf("Win");
else if(apd[i]==0) printf("Lose");
else printf("Loop");
}
printf("\n");
for(int i=1;i<n;i++)
{
if(i>1) printf(" ");
if(bpd[i]==1) printf("Win");
else if(bpd[i]==0) printf("Lose");
else printf("Loop");
}
printf("\n");
}
}
D:这个题一开始我也没思路,然后在一Dalao的指点下才知道线段树优化建边这东西,看了一下,然后就过了。不过第一次写,代码写的好SB。
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+10;
typedef long long LL;
const LL INF=1e17+10;
bool book[maxn<<4];
LL dis[maxn<<4];
int head[maxn<<2],tot,n,q,s,id,vis1[maxn<<1],vis2[maxn<<1];
struct Node
{
int u,v,w,next;
Node(int _u=0,int _v=0,int _w=0,int _next=0):u(_u),v(_v),w(_w),next(_next){}
}edges[maxn<<4];
struct node
{
int v;
LL d;
node(int _v=0,LL _d=0):v(_v),d(_d){}
bool operator < (const node& x)const
{
return d>x.d;
}
};
void addedge(int u,int v,int w)
{
//printf("addedge-> u:%d v:%d w:%d\n",u,v,w);
edges[tot]=Node(u,v,w,head[u]);
head[u]=tot++;
}
void buildtree1(int rt,int l,int r)//edges links from up to down which weight are 0
{
if(vis1[rt]==0) vis1[rt]=++id;
if(l==r)
{
addedge(vis1[rt],l,0);
return;
}
int mid=(l+r)>>1,lson=rt<<1,rson=rt<<1|1;
buildtree1(lson,l,mid);
buildtree1(rson,mid+1,r);
addedge(vis1[rt],vis1[lson],0);
addedge(vis1[rt],vis1[rson],0);
}
void buildtree2(int rt,int l,int r)
{
if(vis2[rt]==0) vis2[rt]=++id;
if(l==r)
{
addedge(l,vis2[rt],0);
return;
}
int mid=(l+r)>>1,lson=rt<<1,rson=rt<<1|1;
buildtree2(lson,l,mid);
buildtree2(rson,mid+1,r);
addedge(vis2[lson],vis2[rt],0);//down to up - weight 0
addedge(vis2[rson],vis2[rt],0);//down to up - weight 0
}
void addedge2(int u,int rt,int l,int r,int ql,int qr,int w)
{
if(l>qr||r<ql) return;
if(ql<=l&&r<=qr)
{
addedge(vis2[rt],u,w);
return;
}
int mid=(l+r)>>1,lson=rt<<1,rson=rt<<1|1;
addedge2(u,lson,l,mid,ql,qr,w);
addedge2(u,rson,mid+1,r,ql,qr,w);
}
void addedge1(int u,int rt,int l,int r,int ql,int qr,int w)
{
if(l>qr||r<ql) return;
if(ql<=l&&r<=qr)
{
//cout<<1<<endl;
//cout<<rt<<" "<<l<<" "<<r<<endl;
addedge(u,vis1[rt],w);
return;
}
int mid=(l+r)>>1,lson=rt<<1,rson=rt<<1|1;
addedge1(u,lson,l,mid,ql,qr,w);
addedge1(u,rson,mid+1,r,ql,qr,w);
}
void init()
{
id=n;
tot=0;
memset(vis1,0,sizeof(vis1));
memset(vis2,0,sizeof(vis2));
memset(book,false,sizeof(book));
memset(head,-1,sizeof(head));
buildtree1(1,1,n);
buildtree2(1,1,n);
}
void dijkstra()
{
priority_queue<node>Q;
for(int i=0;i<=9*n;i++)
{
//addedge(i,i,0);
dis[i]=INF;
}
dis[s]=0;
Q.push(node(s,0));
while(!Q.empty())
{
node a=Q.top();
Q.pop();
int u=a.v;
if(book[u]) continue;
book[u]=true;
//cout<<"u:"<<u<<endl;
for(int i=head[u];~i;i=edges[i].next)
{
int v=edges[i].v,w=edges[i].w;
//cout<<"v:"<<v<<" w:"<<w<<endl;
if(dis[u]+w<dis[v])
{
dis[v]=dis[u]+w;
if(!book[v]) Q.push(node(v,dis[v]));
}
}
}
for(int i=1;i<=n;i++)
{
if(dis[i]==INF) dis[i]=-1;
if(i==1) cout<<dis[i];
else cout<<" "<<dis[i];
}
puts("");
}
int main()
{
int op,u,v,w,l,r;
while(~scanf("%d%d%d",&n,&q,&s))
{
init();
while(q--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
// u -> f1(v,v)
}
else if(op==2)
{
scanf("%d%d%d%d",&u,&l,&r,&w);
addedge1(u,1,1,n,l,r,w);
// u -> f1(l,r)
}
else
{
scanf("%d%d%d%d",&u,&l,&r,&w);
addedge2(u,1,1,n,l,r,w);
// f2(l,r) -> u
}
}
dijkstra();
}
}
E:容易想到贪心,又因为涉及到区间不同数的个数很容易就想到主席树+二分,这样是O(n(logn)^3) 没试过(也许就过了呢),常见优化成主席树上的二分就是O(n(logn)^2)。为什么E题感觉比CD还水...
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,tot,c[maxn*100],lson[maxn*100],rson[maxn*100],T[maxn],a[maxn];
map<int,int>mp;
void init()
{
tot=0;
mp.clear();
}
int buildtree(int l,int r)
{
int root=tot++;
c[root]=0;
if(l!=r)
{
int mid=(l+r)>>1;
lson[root]=buildtree(l,mid);
rson[root]=buildtree(mid+1,r);
}
return root;
}
int update(int root,int pos,int val)
{
int newroot=tot++,tmp=newroot;
int l=1,r=n;
c[newroot]=c[root]+val;
while(l<r)
{
int mid=(l+r)>>1;
if(pos<=mid)
{
rson[newroot]=rson[root],lson[newroot]=tot++;
newroot=lson[newroot],root=lson[root];
r=mid;
}
else
{
lson[newroot]=lson[root],rson[newroot]=tot++;
newroot=rson[newroot],root=rson[root];
l=mid+1;
}
c[newroot]=c[root]+val;
}
return tmp;
}
void updatetree()
{
T[n+1]=buildtree(1,n);
for(int i=n;i>=1;i--)
{
if(mp.find(a[i])==mp.end()) T[i]=update(T[i+1],i,1);
else
{
int tmp=update(T[i+1],mp[a[i]],-1);
T[i]=update(tmp,i,1);
}
mp[a[i]]=i;
}
}
int query(int root,int l,int r,int val)
{
if(c[root]<=val) return r;
if(l==r) return l-1;
int mid=(l+r)>>1;
if (c[lson[root]]<=val) return query(rson[root],mid+1,r,val-c[lson[root]]);
else return query(lson[root],l,mid,val);
}
int main()
{
while(~scanf("%d",&n))
{
init();
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
updatetree();
for(int k=1;k<=n;k++)
{
int tk=1,ans=0,p;
while(tk<=n)
{
int lst=query(T[tk],1,n,k);
tk=lst+1;
ans++;
}
if(k==1) printf("%d",ans);
else printf(" %d",ans);
}
puts("");
}
}