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  } 
View Code

 

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 }
View Code

正解:用两个线段树

一个用来记录最小的那个,还有多少比值之和就会再加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 }
View Code

函数模板来自于网上(

等我把数论概论和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  } 
View Code

 

posted @ 2019-07-17 18:18  moomight  阅读(170)  评论(0编辑  收藏  举报