开始逐渐习惯被多校虐orz 菜是原罪
1004 Game (hdoj 6312)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6312
虽然披着博弈的外壳 但是也算是结论题 一开始开题的时候一看到博弈就不想写了 但是大佬们过题太快了 所以想到可能是结论题
题意:有A和B两个人可以对一个1-n的全排列进行操作 每一次都可以删去一个数和它所有质子 A和B轮流进行操作 先删光全排列为赢 A先手 给出n 判断A的输赢
因为每一次删数操作都会删去1 所以可以忽视掉1 直接看2-n的状态 如果在这个状态下B赢了 那么A先去选择1来转变自己的局面 A可以赢 如果2-n的状态下A赢了 可以不用专门去选择1 保持赢的状态 所以A是必胜的
知道这个结论后 代码就无比的简单了 不过要注意多组输入 这一场都要注意这个问题
代码如下
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int main(){ int n; while(scanf("%d",&n)!=EOF){ printf("Yes\n"); } return 0; }
1011 Swaps and Inversions (hdoj 6318)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6318
树状数组+离散化 求逆序数
题意:给出一个数列 如果一个数的逆序数不为0 则要付出逆序数*x的代价 但是也可以选择交换相邻两项来减少逆序数 每次交换需要付出的代价为y
只要想到这是逆序数 就是一题板子题了 因为相邻两项也可以构成逆序对 所以就可以把问题简化为逆序数和*min(x,y)
逆序数在线性代数中有定义(orz还好没忘记这学期刚学的线代)一个数的逆序数 是在这个数之后所有比它要小的数字个数的和 这里可以用离散化的思想来处理 用树状数组来进行修改和查询
有个小坑 一直wa 后知后觉发现是姿势不对orz 在排序的时候进行特判 差不多一个结构体二重排序(?)
哦对了 会爆int 要开long long
代码如下:
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; const int maxn=1e5+10; typedef long long ll; int c[maxn],pos[maxn]; int n; struct node{ int v; int id; }kk[maxn]; int cmp(node a,node b){ if(a.v==b.v) return a.id<b.id; else return a.v<b.v; } int lowbit(int x){ return x&(-x); } void insert(int i,int x){ while(i<=n){ c[i]+=x; i+=lowbit(i); } } ll getsum(int i){ ll sum=0; while(i>=1){ sum+=c[i]; i-=lowbit(i); } return sum; } int main(){ int x,y; while(~scanf("%d%d%d",&n,&x,&y)){ ll ans=0; for(int i=1;i<=n;i++){ scanf("%d",&kk[i].v); kk[i].id=i; } sort(kk+1,kk+n+1,cmp); for(int i=1;i<=n;i++){ pos[kk[i].id]=i; } memset(c,0,sizeof(c)); for(int i=1;i<=n;i++){ insert(pos[i],1); ans+=i-getsum(pos[i]); } printf("%lld\n",(ll)ans*min(x,y)); } return 0; }