2018 多校2 hdu 6312 6315 6318
6312 d题
博弈论题,Alice先删除1,则变成后手,不删1则为先手,那么无论怎样都是Alice获胜,故所有的都输出Yes
1 #include<iostream> 2 #include<cmath> 3 using namespace std; 4 5 int main() 6 { 7 int n; 8 while(scanf("%d",&n)!=EOF) cout<<"Yes"<<endl; 9 return 0; 10 }
6315 g题
线段树题,本来想区间维护,后来发现不太行,就选择用单点维护,交上去t了
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 const int maxn = 1e5 + 10; 8 double a[maxn]={0},b[maxn]; 9 int tree[400010]; 10 int grade[maxn]={0}; 11 12 void build(int p,int l,int r) 13 { 14 if(l==r){ 15 tree[p]=grade[l]; 16 return; 17 } 18 int mid=(l+r)/2; 19 build(p*2,l,mid); 20 build(p*2+1,mid+1,r); 21 tree[p]=max(tree[p*2],tree[p*2+1]); 22 } 23 24 void change(int p,int l,int r,int x,int num) 25 { 26 if(l==r) { 27 tree[p]+=num;return; 28 } 29 int mid=(l+r)/2; 30 if(x<=mid) change(p*2,l,mid,x,num); 31 else change(p*2+1,mid+1,r,x,num); 32 tree[p]=tree[p*2]+tree[p*2+1]; 33 } 34 35 36 int find(int p,int l,int r,int x,int y) 37 { 38 if(x<=l&&r<=y) return tree[p]; 39 int mid=(l+r)/2; 40 if(y<=mid) return find(p*2,l,mid,x,y); 41 if(x>mid) return find(p*2+1,mid+1,r,x,y); 42 return (find(p*2,l,mid,x,mid)+find(p*2+1,mid+1,r,mid+1,y)); 43 } 44 45 46 47 int main() 48 { 49 int n,q,x,y,c; 50 char str[10]; 51 scanf("%d %d",&n,&q); 52 for(int i=1;i<=n;i++){ 53 scanf("%lf",&b[i]); 54 } 55 build(1,0,n-1); 56 57 while(q--){ 58 scanf("%s %d %d",str,&x,&y); 59 if(strcmp(str,"add")==0){ 60 for(int i=x;i<=y;i++){ 61 a[i]++; 62 c=floor(a[i]/b[i]); 63 if(c!=grade[i]) { 64 int f = c-grade[i]; 65 grade[i]=c; 66 change(1,1,n,i,f); 67 } 68 } 69 } 70 else if(strcmp(str,"query")==0){ 71 int cnt = find(1,1,n,x,y); 72 cout<<cnt<<endl; 73 } 74 } 75 return 0; 76 77 }
正解:用两个线段树
一个用来记录最小的那个,还有多少比值之和就会再加1的值
一个用来记录比值之和
晚上补代码
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 #include <algorithm> 6 #define maxn 100005 7 using namespace std; 8 typedef long long ll; 9 struct Tree{ 10 ll sum,valb,minn,add; 11 }tr[maxn*4]; 12 int n,q; 13 int a[maxn],b[maxn]; 14 void push_up(int rt){ 15 tr[rt].minn=min(tr[rt*2].minn,tr[rt*2+1].minn); 16 tr[rt].sum=tr[rt*2].sum+tr[rt*2+1].sum; 17 } 18 void push_down(int rt){ 19 if(tr[rt].add){ 20 tr[rt*2].add+=tr[rt].add; 21 tr[rt*2+1].add+=tr[rt].add; 22 tr[rt*2].minn-=tr[rt].add; 23 tr[rt*2+1].minn-=tr[rt].add; 24 tr[rt].add=0; 25 } 26 } 27 void build(int l,int r,int rt){ 28 tr[rt].add=tr[rt].sum=0; 29 if(l==r){ 30 tr[rt].minn=tr[rt].valb=b[l]; 31 tr[rt].sum=0; 32 return; 33 } 34 int mid=(l+r)/2; 35 build(l,mid,rt*2); 36 build(mid+1,r,rt*2+1); 37 push_up(rt); 38 } 39 void update(int L,int R,int l,int r,int rt){ 40 if(L<=l&&R>=r&&tr[rt].minn>1){ 41 tr[rt].add++; 42 tr[rt].minn--; 43 return; 44 } 45 if(l==r&&tr[rt].minn==1){ 46 tr[rt].sum++; 47 tr[rt].minn=tr[rt].valb; 48 tr[rt].add=0; 49 return; 50 } 51 int mid=(l+r)/2; 52 push_down(rt); 53 if(L<=mid) update(L,R,l,mid,rt*2); 54 if(R>mid) update(L,R,mid+1,r,rt*2+1); 55 push_up(rt); 56 } 57 ll query(int L,int R,int l,int r,int rt){ 58 if(L<=l&&R>=r){ 59 return tr[rt].sum; 60 } 61 int mid=(l+r)/2; 62 push_down(rt); 63 ll ans=0; 64 if(L<=mid) ans+=query(L,R,l,mid,rt*2); 65 if(R>mid) ans+=query(L,R,mid+1,r,rt*2+1); 66 return ans; 67 } 68 int main() 69 { 70 while(~scanf("%d%d",&n,&q)){ 71 for(int i=1;i<=n;i++){ 72 scanf("%d",&b[i]); 73 } 74 build(1,n,1); 75 while(q--){ 76 string str; 77 cin>>str; 78 int l,r; 79 scanf("%d%d",&l,&r); 80 if(str[0]=='a'){ 81 update(l,r,1,n,1); 82 } 83 else{ 84 ll res=query(l,r,1,n,1); 85 printf("%lld\n",res); 86 } 87 } 88 } 89 return 0; 90 }
函数模板来自于网上(
等我把数论概论和y总课看完了补
6318 j题
求逆序对,然后相乘即可
1 #include<iostream> 2 #include<cmath> 3 #include<algorithm> 4 using namespace std; 5 const int maxn = 1e5+10; 6 int q[maxn],tmp[maxn]; 7 8 long long merge_sort(int q[], int l, int r) 9 { 10 if (l >= r) return 0; 11 12 int mid = l + r >> 1; 13 14 long long res = merge_sort(q, l, mid) + merge_sort(q, mid + 1, r); 15 16 int k = 0, i = l, j = mid + 1; 17 while (i <= mid && j <= r) 18 if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ]; 19 else 20 { 21 res += mid - i + 1; 22 tmp[k ++ ] = q[j ++ ]; 23 } 24 while (i <= mid) tmp[k ++ ] = q[i ++ ]; 25 while (j <= r) tmp[k ++ ] = q[j ++ ]; 26 27 for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j]; 28 29 return res; 30 } 31 int main() 32 { 33 int n,x,y; 34 long long p; 35 while(scanf("%d %d %d",&n,&x,&y)!=EOF) 36 { 37 for(int i=0;i<n;i++){ 38 scanf("%d",&q[i]); 39 } 40 p=merge_sort(q,0,n-1); 41 unsigned long long cnt=p*min(x,y); 42 printf("%llu\n",cnt); 43 } 44 return 0; 45 }
一以贯之的努力 不得懈怠的人生 每天的微小积累会决定最终结果 ————————裴之
欢迎加我QQ:1136244161一起讨论,共同进步