2017ACM/ICPC广西邀请赛-重现赛
HDU 6188 Duizi and Shunzi
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6188
思路:
签到题,以前写的。
实现代码:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<stack> #include<map> #include<vector> #include<set> using namespace std; const int MAX=1e5+10; int main() { int n,m,a[MAX],p,ans,k; while(scanf("%d",&n)!=EOF) { ans=0; for(int i = 1;i <= n;i ++) a[i]=0; for(int i = 1;i <= n;i ++) cin>>p,a[p]++; for(int i = 1;i <= n;i ++) { if(a[i]>=2) { ans+=a[i]/2; a[i]%=2; } if(i<=n-2&&a[i]&&a[i+1]%2&&a[i+2]) a[i]--,a[i+1]--,a[i+2]--,ans+=1; } cout<<ans<<endl; } }
HDU 6182 A Math Problem
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6182
思路: 签到
实现代码:
#include<bits/stdc++.h> using namespace std; #define ll long long const ll M = 1e18+5; ll a[100009]; int main() { ll k = 0; ll n,m; for(ll i = 1;i<=15;i++){ ll ans = 1; for(ll j=1;j<=i;j++){ ans*=i; } //cout<<ans<<endl; if(ans<=M) a[k++] = ans; else break; } while(scanf("%lld",&n)!=EOF){ if(n>437893890380859375) cout<<15<<endl; else{ for(ll i=0;i<k;i++){ if(a[i]>n){ cout<<i<<endl;break; } else if(a[i]==n){ cout<<i+1<<endl;break; } } } } return 0; }
HDU 6186 CS Course
链接: http://acm.hdu.edu.cn/showproblem.php?pid=6186
思路:签到题
实现代码:
#include<bits/stdc++.h> using namespace std; const int M = 100050; #define ll long long ll a[M],or1[M],or2[M],and2[M],and1[M],xor1[M],xor2[M]; int main() { ll n,q,i,x; while(scanf("%lld%lld",&n,&q)!=EOF){ for(i=1;i<=n;i++){ scanf("%lld",&a[i]); } or1[1] = a[1];and1[1] = a[1]; xor1[1] = a[1]; for(i=2;i<=n;i++){ or1[i] = (or1[i-1]|a[i]); and1[i] = (a[i]&and1[i-1]); xor1[i] = (xor1[i-1]^a[i]); } or2[n] = a[n]; and2[n] = a[n];xor2[n] = a[n]; for(i=n-1;i>=1;i--){ or2[i] = (a[i]|or2[i+1]); and2[i] = (a[i]&and2[i+1]); xor2[i] = (a[i]^xor2[i+1]); } //cout<<and1[2]<<" "<<(a[1]&a[2])<<endl; ll y; for(i=0;i<q;i++){ scanf("%lld",&y); if(y==1) printf("%lld %lld %lld\n",and2[2],or2[2],xor2[2]); else{ if(y==n) printf("%lld %lld %lld\n",and1[n-1],or1[n-1],xor1[n-1]); else printf("%lld %lld %lld\n",(and1[y-1]&and2[y+1]),(or1[y-1]|or2[y+1]),(xor1[y-1]^xor2[y+1])); } } } return 0; }
HDU 6183 Color it
链接: http://acm.hdu.edu.cn/showproblem.php?pid=6183
思路:线段树+动态开点
有50种颜色,对每一种颜色建一颗线段树维护,动态开点。
第一种操作:使点(x,y)的颜色变为c
第二种:询问(1,y1),(x,y2)两点间的颜色种类数量
我们可以以y轴建线段树,横坐标为值,那么要确定两点之前是否存在某种颜色,只要询问下每个颜色在y1,y2之间最小的值(也就是横坐标).判断下最小值是否小于第二种操作给出的x,如果小于的话就代表两点间存在这种颜色。
突然发现这道题以前也写过。。。。
实现代码:
#include<bits/stdc++.h> using namespace std; #define ll long long #define mid int m = (l + r) >> 1 const int M = 1e6+10; int n = 1e6,flag=0; int sum[M],ne=0,ls[M],rs[M],rt[100]; void update(int &k,int l,int r,int p,int num){ if(!k){ //如果当前区间未拓展,拓展并赋值 k = ++ne; sum[k] = num; } sum[k] = min(sum[k],num);//当前区间有值,更新下最小值 if(l == r) return ; mid; if(p <= m) update(ls[k],l,m,p,num); else update(rs[k],m+1,r,p,num); } void query(int k,int L,int R,int l,int r,int up){ if(!k||flag) return ; if(L <= l&&R >= r){ if(sum[k]<=up) flag = 1; return; } mid; if(L <= m) query(ls[k],L,R,l,m,up); if(R > m) query(rs[k],L,R,m+1,r,up); return ; } void init(){ memset(rt,0,sizeof(rt)); memset(sum,0,sizeof(sum)); memset(ls,0,sizeof(ls)); memset(rs,0,sizeof(rs)); ne = 0; } int main() { int op,x,y,z; while(~scanf("%d",&op)){ if(op == 0) init(); else if(op == 1){ scanf("%d%d%d",&x,&y,&z); update(rt[z],1,n,y,x); } else if(op == 2){ scanf("%d%d%d",&x,&y,&z); int ans = 0 ; for(int i = 0;i <= 50;i ++){ flag = 0; query(rt[i],y,z,1,n,x); if(flag) ans++; } printf("%d\n",ans); } else return 0; } return 0; }
HDU 6191 Query on A Tree
链接: http://acm.hdu.edu.cn/showproblem.php?pid=6191
思路:dfs序 + 可持久化Trie树
用dfs序把树转换成序列,由于dfs序的特性,子树在序列中是连续的一段区间,那么对这段区间我们可以用可持久化trie来查询与x异或最大的值。
实现代码:
#include<bits/stdc++.h> using namespace std; #define ll long long const int M = 1e5+10; int a[M]; int rt[M],tot,tree[M<<5][2],son[M<<5][2],idx,in[M],out[M],cnt,head[M]; vector<int>g[M]; template <class T> void read(T &x){ char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x){ if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } void Insert(int old,int now,int x,int pos){ if(pos < 0) return; int tmp = (x&(1<<pos))>0; tree[now][tmp] = tree[old][tmp] + 1; tree[now][tmp^1] = tree[old][tmp^1]; son[now][tmp^1] = son[old][tmp^1]; Insert(son[old][tmp],son[now][tmp]=++idx,x,pos-1); } void dfs(int u){ in[u] = ++tot; Insert(rt[in[u]-1],rt[in[u]]=++idx,a[u],30); for(int i = 0;i < g[u].size();i ++){ dfs(g[u][i]); } out[u] = tot; } int query(int old,int now,int x,int ans,int pos){ if(pos < 0) return ans; int tmp=!!(x&(1<<pos)); if(tree[now][tmp^1]>tree[old][tmp^1]) return query(son[old][tmp^1],son[now][tmp^1],x,ans|(1<<pos),pos-1); else return query(son[old][tmp],son[now][tmp],x,ans,pos-1); } int init(){ memset(rt,0,sizeof(rt)); memset(son,0,sizeof(son)); memset(tree,0,sizeof(tree)); idx = 0,tot = 0; } int main(){ int n,q,x,z,y; while(scanf("%d%d",&n,&q)!=EOF){ init(); for(int i = 1;i <= n;i ++){ read(a[i]); } for(int i = 2;i <= n;i ++){ read(z); g[z].push_back(i); } dfs(1); while(q--){ read(x),read(y); write(query(rt[in[x]-1],rt[out[x]],y,0,30)); putchar('\n'); } for(int i = 1;i <= n;i ++) g[i].clear(); } return 0; }