【模板】逆序数,java大数,2014 Multi-University Training Contest 5,
来源:互联网 发布:自卫武器 知乎 编辑:程序博客网 时间:2024/05/21 07:06
2014 Multi-University Training Contest 5 出题人————叉姐
队内训练,感觉有点迷
1001
hdu 4911 Inversion
给一串数字,允许交换相邻的数字最多k次
找到最少的逆序数 : (i,j) 有iaj
由组合数学知识,一个数组的逆序数等于使其变成有序列(非降序)所进行得相邻元素交换的最少次数。
仔细想想,i,j,k swap(i,j) 并不会影响k的逆序数
所以这题就是 逆序数-k; 用线段树就好了
之前2016 多校补题补过逆序数,但那个题是1-n的全排列,所以没有相同的ai,这里需要离散化。这里“ 按位置插线段树“ 也很精髓
#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<queue>#include<stack>#include<string.h>#include<map>#include<set>using namespace std;#define ll __int64/* */struct seg{ int l,r; ll v;}st[100005<<2];void build(int l,int r,int id){ int mid=(l+r)>>1; st[id].v=0; st[id].l=l; st[id].r=r; if(l==r) return; build(l,mid,id<<1); build(mid+1,r,(id<<1)+1);}void push_up(int id){ st[id].v=max(st[id].v,st[id<<1].v+st[id*2+1].v);}void update(int p,int id){// printf("id=%d\n",id); if(st[id].l==p && st[id].r==p){ st[id].v++; return; } int mid=(st[id].l+st[id].r)/2; if(p<=mid) update(p,id*2); else update(p,id*2+1); push_up(id);}ll qur(int l,int r,int rt){ if(st[rt].l==l &&st[rt].r==r){ return st[rt].v; } push_up(rt); int mid=(st[rt].l+st[rt].r)>>1; int ans=0; if(mid>=r){ ans+=qur(l,r,rt<<1); } else if(l>mid){ ans+=qur(l,r,(rt<<1)+1); } else{ ans+=qur(l,mid,rt<<1); ans+=qur(mid+1,r,(rt<<1)+1); } return ans;}int a[100005];int b[100005];int main() { //freopen("1.txt","r",stdin); int n,k; while(~scanf("%d %d",&n,&k)){ map<int,int>pos; for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i]; sort(b+1,b+n+1); for(int i=1;i<=n;i++){ //log的离散化,也许有更好离散化方法。 if(!pos[b[i]]) pos[b[i]]=i; } build(1,n,1); ll ans=0; for(int i=1;i<=n;i++){ int p=pos[a[i]]; //离散化后的大小 update(p,1);//+1 ll cnt=qur(1,p,1); //前面比他小或等于的有cnt个// printf("cnt=%d\n",cnt); ans+=i-cnt; } ans-=k; if(ans<0) ans=0; printf("%I64d\n",ans); } return 0;}
1009 Exclusive or
题意 不知, 小学弟直接把公式交给我,我打大数模板就好了,稳。
这里找了一个比较好的大数模板,因为需要使用记忆化搜索,还需要学一下map该如何使用。
import java.util.*;import java.math.*; import java.io.*;import java.util.Scanner; public class Main { public static BigInteger bigInteger0=BigInteger.valueOf(0); public static BigInteger bigInteger1=BigInteger.valueOf(1); public static BigInteger bigInteger2=BigInteger.valueOf(2); public static BigInteger bigInteger4=BigInteger.valueOf(4); public static BigInteger bigInteger6=BigInteger.valueOf(6); public static HashMap<BigInteger,BigInteger> map=new HashMap<BigInteger,BigInteger>(); public static BigInteger dfs(BigInteger n){ if(map.containsKey(n)) return map.get(n); BigInteger ans=BigInteger.valueOf(0); BigInteger t=n.divide(bigInteger2); BigInteger r=n.remainder(bigInteger2); BigInteger a=new BigInteger ("1"); BigInteger b=new BigInteger ("1"); a=dfs(t); b=dfs(t.subtract(bigInteger1)); if(r.equals(bigInteger1)) ans=( bigInteger4.multiply(a) ).add(bigInteger6.multiply(t)); else { ans=bigInteger2.multiply(a); ans=ans.add(bigInteger2.multiply(b)); ans=ans.add(bigInteger4.multiply(t)); ans=ans.subtract(bigInteger4); } map.put(n, ans); return ans; } public static void main(String[] args) { Scanner cin = new Scanner (System.in); BigInteger x; map.put(bigInteger0, bigInteger0); map.put(bigInteger1,bigInteger0); while(cin.hasNext()) { x=cin.nextBigInteger(); System.out.println(dfs(x)); } }}
1010 Matrix multiplication
题意很简单:求两个矩阵相乘 800*800的矩阵
最让我没想到的是: 判断会比相乘的时间还要多。
以后做常数优化,记住: 稍作判断,宁愿做运算,也尽量少做判断。还有貌似a=a+b,比a+=b, 要快,(没验证过,不知真假)
#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<queue>#include<stack>#include<string.h>#include<map>#include<set>using namespace std;#define ll __int64/*把 每i行的第j个 放进 map<pair<i,j>,int >所以 aij *bji 存在int */int matr1[805][805];int matr2[805][805];int matr3[805][805];int main() { //freopen("1.txt","r",stdin); int n; while(~scanf("%d",&n)){ for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&matr1[i][j]),matr1[i][j]%=3; for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) scanf("%d",&matr2[i][j]),matr2[i][j]%=3; memset(matr3,0,sizeof(matr3)); for (int i=1;i<=n;i++){ for (int k=1;k<=n;k++){ if(matr1[i][k]) for (int j=1;j<=n;j++){ matr3[i][j]+=matr1[i][k]*matr2[k][j]; } } } for (int i=1;i<=n;i++){ printf("%d",matr3[i][1]%3); for (int j=2;j<=n;j++){ printf(" %d",matr3[i][j]%3); } printf("\n"); } } return 0;}
1005
http://acm.hdu.edu.cn/showproblem.php?pid=4915
题意:
给一个括号的串,包括( ) 和? ,问当需要构成匹配的串时,我们只能构成为唯一的,不能构成合法的,还是能够成很多种。
>
??
????
(??
Unique
Many
None
看了别人的代码,反正当时wa了两发,用模拟做的,看了别人贪心写的很简单
#include<iostream>#include<cstdio>#include<algorithm>#include<vector>#include<queue>#include<stack>#include<string.h>#include<map>#include<set>using namespace std;#define ll __int64using namespace std;#define N 1000005 /*从前扫一遍,记录最大和最小的可能的左括号的值如果最小值>最大值,则必定不行从后扫一遍,同样记录最大和最小的可能的左括号的值如果最小值>最大值,no最后再扫一遍对于每个ia[i][0],b[i][0] 代表[1,i]左括号最小的个数,和[i+1,len]右括号最小的个数他们中的最大值 =la[i][1],b[i][1] 代表[1,i]左括号最多的个数,和[i+1,len]右括号最多的个数他们中的最小值 =rl<r如果前者大于后者,则不行如果后者大于前者则有多重解如果相等则为唯一解 * */char s[N];int a[N][2]; //存左括号 最小 0 最大 1int b[N][2]; //int len,flag;void ans(int i){ if(i==1) printf("Unique\n"); else if(i==2) printf("Many\n"); else printf("None\n");}int main(){ //freopen("1.txt","r",stdin); while(~scanf("%s",s+1)) { len = strlen(s+1); if(len&1){ printf("None\n"); continue; } memset(a,0,sizeof(a)); memset(b,0,sizeof(b)); flag = 1; for(int i=1;i<=len;i++) { a[i][0]=a[i-1][0]; a[i][1]=a[i-1][1]; if(s[i]=='(') //出现( ,最小最多都+1 a[i][0]++,a[i][1]++; else if(s[i]==')') { if(!a[i-1][0]) //控制最小的(应该>0, 但不控制最多的,以及第一个?=( a[i][0]=1; else a[i][0]--; a[i][1]--; } else if(s[i]=='?'){ if(!a[i-1][0]) //把?当)看 a[i][0]=1; else a[i][0]--; a[i][1]++; //对于最多的吧 ?当(看 } if(a[i][0]>a[i][1]){ // 例如: )( ,?))(?? flag=0; break; } } if(flag==0){ printf("None\n"); continue; } for(int i=len;i>=1;i--) {// b[i][0] = b[i+1][0]; b[i][1] = b[i+1][1]; if (s[i] == ')') b[i-1][0] = b[i][0] + 1, b[i - 1][1] = b[i][1] + 1; else if (s[i] == '(') { if (!b[i][0]) b[i-1][0] = 1; else b[i - 1][0] = b[i][0] - 1; b[i - 1][1] = b[i][1] - 1; } else if (s[i] == '?') { if (!b[i][0]) b[i - 1][0] = 1; else b[i - 1][0] = b[i][0] - 1; b[i - 1][1] = b[i][1] + 1; } if(b[i][0]>b[i][1]){ flag=0; break; } } if(flag==0){ printf("None\n"); continue; } int l,r; flag = 1; for(int i=1;i<=len;i++) {/* printf("i=%d a0 b=%d %d\n",i,a[i][0],b[i][0]); printf(" a1 b=%d %d\n",a[i][1],b[i][1]); l = max(a[i][0],b[i][0]); //左右括号的最小值 r = min(a[i][1],b[i][1]); // if(l>r) {flag=0;break;} if(l<r) {flag=2;break;} 因为已知ab[i][1]>=ab[i][0] 所以可以改写 */ if(a[i][0]>b[i][1] || b[i][0] >a[i][1]){ flag=0;break; } if(a[i][1] >b[i][0] && b[i][1]>a[i][0]){ flag=2;break; } } if(flag==0) printf("None\n"); else if(flag==1) printf("Unique\n"); else if(flag==2) printf("Many\n"); } return 0;}
- 【模板】逆序数,java大数,2014 Multi-University Training Contest 5,
- 【2014 Multi-University Training Contest 5】 Inversion (离散化,树状数组求逆序数)
- 【2014 Multi-University Training Contest 6】 G. Series 1(n阶差分,组合数,大数)
- 2015 Multi-University Training Contest 5 1009 模板
- (HDU 5792)2016 Multi-University Training Contest 5 World is Exploding (逆序数、顺序数、树状数组)
- 2016 Multi-University Training Contest 4 - 1012(树状数组求逆序数 )
- 【substr + 逆序数+ 线段树push_up的位置!!!】2016 Multi-University Training Contest 4
- 2013 Multi-University Training Contest 1 I-number 大数
- hdu4915 Parenthese sequence 2014 Multi-University Training Contest 5
- 2014 Multi-University Training Contest 5 HDOJ 4911 Inversion
- 2014 Multi-University Training Contest 5 HDOJ 4920 Matrix multiplication
- hdu4911 Inversion 2014 Multi-University Training Contest 5
- hdu4920 Matrix multiplication 2014 Multi-University Training Contest 5
- hdu 4915 Parenthese sequence--2014 Multi-University Training Contest 5
- hdu 4911 Inversion--2014 Multi-University Training Contest 5
- hdu 4920 Matrix multiplication--2014 Multi-University Training Contest 5
- hdu 4911 Inversion ( 2014 Multi-University Training Contest 5)
- hdu 4911 Inversion 2014 Multi-University Training Contest 5
- win10下安装quartus ii15.0+ModelSim10.4
- Linux为什么能发展壮大
- 类之间的关系
- Mapped Statements collection does not contain value for
- mongodb开发--java
- 【模板】逆序数,java大数,2014 Multi-University Training Contest 5,
- viewpager同步
- threejs设置对象层次
- 数据结构 树、二叉树、完全二叉树
- 如何在Windows下安装gensim
- LeetCode : Number of Boomerangs
- [勇者闯LeetCode] 215. Kth Largest Element in an Array
- zookeeper 安装 windows环境
- php面试常用题目精解(二)