标签:shu else efi scan hdu nbsp view ble tar
题意:
Alice和Bob先后手玩游戏,每次可以从一个集合中拿出一个数(初始为1~n),拿出之后,这个数的所有因数都会从这个集合中消失,谁没有数可拿时,就输了。问Alice是否能赢?
分析:
如果先手拿x为必胜态,那么Alice一定能赢;如果先手拿x为必输态,那么Alice先手拿1,则必输态转移给Bob,所以Alice一定能赢。
代码:
#include <cmath> #include <vector> #include <stdio.h> #include <iostream> using namespace std; #define ll long long const int maxn=1e5+100; int main() { // freopen("in.txt","r",stdin); int n; while(scanf("%d",&n)!=EOF) { printf("Yes\n"); } return 0; }
题意:
给出b数组,和q次操作。如果为add l r操作,则把a数组【l,r】区间的值都加上一,query l r操作询问【l,r】区间a【i】/b【i】(向下取整)的和。
分析:
利用线段树存下区间的最大a[i]和最小b[i]值,当a[i]>=b[i]时,说明c[i]的值需要加一(c[i]=a[i]/b[i]),sum存储对应区间的c[i]之和,具体看代码注释。
代码:
#include <cmath> #include <vector> #include <stdio.h> #include <iostream> using namespace std; #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int maxn=1e5+100; int n,q,l,r,c; char s[10]; ll b[maxn]; //add[rt]:延迟标记,rt区间的a[i]值需要加上add[rt] //sum[rt]:ai/bi的区间和 //minval[rt]:rt区间的最小b[i]值 //maxval[rt]:rt区间的最大a[i]值 ll sum[maxn<<2],add[maxn<<2],minval[maxn<<2],maxval[maxn<<2]; void PushUp(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; minval[rt]=min(minval[rt<<1],minval[rt<<1|1]); maxval[rt]=max(maxval[rt<<1],maxval[rt<<1|1]); } void PushDown(int rt) { if(add[rt]){ add[rt<<1]+=add[rt]; add[rt<<1|1]+=add[rt]; maxval[rt<<1]+=add[rt]; maxval[rt<<1|1]+=add[rt]; add[rt]=0; } } void build(int l,int r,int rt) { add[rt]=0; if(l==r){ sum[rt]=0; maxval[rt]=0; minval[rt]=b[l]; return; } int m=(l+r)>>1; build(lson); build(rson); PushUp(rt); } void update(int L,int R,int c,int l,int r,int rt) { if(L<=l&&r<=R){ maxval[rt]+=c; if(maxval[rt]<minval[rt]){ add[rt]+=c; return; } if(l==r&&maxval[rt]>=minval[rt]){ sum[rt]++; //第i次贡献时,maxval[rt]的值为i*b[l] //所以每次maxval[rt]贡献后,minval[rt]的值需要加上b[l] minval[rt]+=b[l]; return; } } PushDown(rt); int m=(l+r)>>1; if(L<=m) update(L,R,c,lson); if(R>m) update(L,R,c,rson); PushUp(rt); } ll query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R){ return sum[rt]; } PushDown(rt); ll ans=0; int m=(l+r)>>1; if(L<=m) ans+=query(L,R,lson); if(R>m) ans+=query(L,R,rson); return ans; } void debug(int l,int r,int rt) { if(l==r){ printf("debug:%d %d\n",l,sum[rt]); return; } int m=(l+r)>>1; debug(lson); debug(rson); } int main() { // freopen("in.txt","r",stdin); while(scanf("%d%d",&n,&q)!=EOF) { for(int i=1;i<=n;i++){ scanf("%lld",&b[i]); } build(1,n,1); for(int j=1;j<=q;j++){ scanf("%s%d%d",s,&l,&r); if(s[0]==‘a‘){ update(l,r,1,1,n,1); // debug(1,n,1); } else { printf("%lld\n",query(l,r,1,n,1)); } } } return 0; }
题意:
给出一个序列,如果存在一对逆序对需要花费x元,现在可以对两个相邻的元素进行交换,每次交换需要花费y元,问最少要花费多少钱?
分析:
首先一次交换能够减少1对逆序对,那么num对逆序对,就需要num次交换。如果交换i次,花费cost=i*y+(num-i)*x=num*x-i*(y-x),不难看出,mincost=min(x,y)*num。
代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int maxn=1e5+100; int sum[maxn<<2],x[maxn],Hash[maxn]; void PushUp(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void build(int l,int r,int rt) { sum[rt]=0; if(l==r){ return; } int m=(l+r)>>1; build(lson); build(rson); } void update(int p,int add,int l,int r,int rt) { if(l==r){ sum[rt]+=add; return; } int m=(l+r)>>1; if(p<=m) update(p,add,lson); else update(p,add,rson); PushUp(rt); } int query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R){ return sum[rt]; } int ans=0; int m=(l+r)>>1; if(L<=m) ans+=query(L,R,lson); if(R>m) ans+=query(L,R,rson); return ans; } int main() { // freopen("in.txt","r",stdin); int n,costx,costy; while(scanf("%d%d%d",&n,&costx,&costy)!=EOF) { ll cntx=0,cnty=0; build(0,n-1,1); for(int i=0;i<n;i++){ scanf("%d",&x[i]); Hash[i]=x[i]; } sort(Hash,Hash+n); int sz=unique(Hash,Hash+n)-Hash; for(int i=0;i<n;i++){ x[i]=lower_bound(Hash,Hash+sz,x[i])-Hash; } for(int i=0;i<n;i++){ cntx+=query(x[i]+1,n-1,0,n-1,1); update(x[i],1,0,n-1,1); } cnty=cntx; ll ans=min(cntx*costx,cnty*costy); printf("%lld\n",ans); } return 0; }
2018 Multi-University Training Contest 2
标签:shu else efi scan hdu nbsp view ble tar
原文地址:https://www.cnblogs.com/shutdown113/p/9371135.html