zoukankan      html  css  js  c++  java
  • 2014 ACM/ICPC Asia Regional Shanghai Online

    Tree http://acm.hdu.edu.cn/showproblem.php?pid=5044

    树链剖分,区间更新的时候要用on的左++右--的标记方法,要手动扩栈,用c++交,综合以上的条件可过。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #pragma comment(linker, "/STACK:36777216")
      5 #define mt(a,b) memset(a,b,sizeof(a))
      6 using namespace std;
      7 typedef __int64 LL;
      8 const int M=100010;
      9 struct G{
     10     struct E{
     11         int v,next;
     12     }e[M<<1];
     13     int le,head[M];
     14     void init(){
     15         le=0;
     16         mt(head,-1);
     17     }
     18     void add(int u,int v){
     19         e[le].v=v;
     20         e[le].next=head[u];
     21         head[u]=le++;
     22     }
     23 }g;
     24 int n,val[M],fa[M],dep[M],num[M],son[M],top[M],sid[M];
     25 void dfs(int u){
     26     num[u]=1;
     27     son[u]=0;
     28     for(int i=g.head[u];~i;i=g.e[i].next){
     29         int v=g.e[i].v;
     30         if(v!=fa[u]){
     31             fa[v]=u;
     32             dep[v]=dep[u]+1;
     33             dfs(v);
     34             if(num[son[u]]<num[v]) son[u]=v;
     35             num[u]+=num[v];
     36         }
     37     }
     38 }
     39 void get(int u,int Top){
     40     sid[u]=++n;
     41     top[u]=Top;
     42     if(son[u]) get(son[u],top[u]);
     43     for(int i=g.head[u];~i;i=g.e[i].next){
     44         int v=g.e[i].v;
     45         if(v!=fa[u]&&v!=son[u]){
     46             get(v,v);
     47         }
     48     }
     49 }
     50 LL lazy[M],ans[M];
     51 void query(){
     52     LL now=0;
     53     for(int i=1;i<=n;i++){
     54         now+=lazy[i];
     55         ans[i]=now;
     56     }
     57 }
     58 void update(int x,int y,int z){
     59     lazy[x]+=z;
     60     lazy[y+1]-=z;
     61 }
     62 void worknode(int x,int y,int z){
     63     int tx=top[x],ty=top[y];
     64     while(tx!=ty){
     65         if(dep[tx]<dep[ty]){
     66             swap(tx,ty);
     67             swap(x,y);
     68         }
     69         update(sid[tx],sid[x],z);
     70         x=fa[tx];
     71         tx=top[x];
     72     }
     73     if(dep[x]>dep[y]) swap(x,y);
     74     update(sid[x],sid[y],z);
     75 }
     76 void workedge(int x,int y,int z){
     77     int tx=top[x],ty=top[y];
     78     while(tx!=ty){
     79         if(dep[tx]<dep[ty]){
     80             swap(tx,ty);
     81             swap(x,y);
     82         }
     83         update(sid[tx],sid[x],z);
     84         x=fa[tx];
     85         tx=top[x];
     86     }
     87     if(x==y) return ;
     88     if(dep[x]>dep[y]) swap(x,y);
     89     update(sid[son[x]],sid[y],z);
     90 }
     91 struct IN{
     92     int type,u,v,w;
     93 }in[M];
     94 struct EDGE{
     95     int u,v;
     96 }edge[M];
     97 int main(){
     98     int t,N,m,u,v;
     99     while(~scanf("%d",&t)){
    100         int cas=1;
    101         while(t--){
    102             scanf("%d%d",&N,&m);
    103             g.init();
    104             for(int i=0;i<N-1;i++){
    105                 scanf("%d%d",&u,&v);
    106                 g.add(u,v);
    107                 g.add(v,u);
    108                 edge[i].u=u;
    109                 edge[i].v=v;
    110             }
    111             n=fa[1]=dep[1]=num[0]=0;
    112             dfs(1);
    113             get(1,1);
    114             char op[8];
    115             for(int i=0;i<m;i++){
    116                 scanf("%s%d%d%d",op,&in[i].u,&in[i].v,&in[i].w);
    117                 if(op[3]=='1') in[i].type=1;
    118                 else           in[i].type=2;
    119             }
    120             mt(lazy,0);
    121             for(int i=0;i<m;i++){
    122                 if(in[i].type&1) worknode(in[i].u,in[i].v,in[i].w);
    123             }
    124             printf("Case #%d:
    ",cas++);
    125             query();
    126             for(int i=1;i<=N;i++){
    127                 if(i>1) printf(" ");
    128                 printf("%I64d",ans[sid[i]]);
    129             }
    130             puts("");
    131             mt(lazy,0);
    132             for(int i=0;i<m;i++){
    133                 if(in[i].type==2) workedge(in[i].u,in[i].v,in[i].w);
    134             }
    135             query();
    136             for(int i=0;i<N-1;i++){
    137                 int u=edge[i].u;
    138                 int v=edge[i].v;
    139                 if(dep[u]<dep[v]){
    140                     swap(u,v);
    141                 }
    142                 if(i) printf(" ");
    143                 printf("%I64d",ans[sid[u]]);
    144             }
    145             puts("");
    146         }
    147     }
    148     return 0;
    149 }
    View Code

    Contest http://acm.hdu.edu.cn/showproblem.php?pid=5045

    根据题目要求,任意时刻都不能出现两个人做题数量的差大于1,也就是差要<=1,也就是m个问题要分成长度为n的等长的几块,每块里面一人做一个。

    问题转化为n个人n题目,如何选一种排列来获得最大价值,若暴力枚举,复杂度是10!,所以用状态压缩,降为2^10,从000推到111.

    转移时看哪个人没做过题,那么就可以让他做,状态就是他这位变为1,值就是当前状态的值加上这个人做当前的题目可获得的价值,当前的题目正好等于已做过题的人的个数+1.

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define mt(a,b) memset(a,b,sizeof(a))
     5 using namespace std;
     6 double a[16][1024],dp[1<<10];
     7 int one(int x){
     8     int res=0;
     9     while(x){
    10         if(x&1) res++;
    11         x>>=1;
    12     }
    13     return res;
    14 }
    15 int main(){
    16     int t,n,m;
    17     while(~scanf("%d",&t)){
    18         int cas=1;
    19         while(t--){
    20             scanf("%d%d",&n,&m);
    21             for(int i=0;i<n;i++){
    22                 for(int j=0;j<m;j++){
    23                     scanf("%lf",&a[i][j]);
    24                 }
    25             }
    26             int s=0,num,all=1<<n;
    27             bool flag=true;
    28             double ans=0;
    29             while(flag){
    30                 flag=false;
    31                 if(s+n<m){
    32                     flag=true;
    33                     num=n;
    34                 }
    35                 else{
    36                     num=m-s;
    37                 }
    38                 mt(dp,0);
    39                 for(int i=0;i<all;i++){
    40                     int yi=one(i);
    41                     if(yi>=num) continue;
    42                     for(int j=0;j<n;j++){
    43                         if((i>>j)&1) continue;
    44                         int next=i|(1<<j);
    45                         dp[next]=max(dp[next],dp[i]+a[j][s+yi]);
    46                     }
    47                 }
    48                 double big=0;
    49                 if(num==n){
    50                     big=dp[all-1];
    51                 }
    52                 else{
    53                     for(int i=0;i<all;i++){
    54                         if(one(i)==num){
    55                             big=max(big,dp[i]);
    56                         }
    57                     }
    58                 }
    59                 ans+=big;
    60                 s+=n;
    61             }
    62             printf("Case #%d: %.5f
    ",cas++,ans);
    63         }
    64     }
    65     return 0;
    66 }
    View Code

    Sawtooth http://acm.hdu.edu.cn/showproblem.php?pid=5047

    根据另一个类似的题目可以猜想出,这种分割方法出来的平面个数应该是个一元二次函数,a*x^2+b*x+c,过3个点,0的时候是1个平面,题目还输入两组,三个进去解出方程的abc,然后输入x就可以输出值了。

     1 #include<cstdio>
     2 #include<cstring>
     3 #define mt(a,b) memset(a,b,sizeof(a))
     4 const int M=32;
     5 class Hp { //高精度类
     6     int len,s[M];
     7 public:
     8     void init(char ch[]) {
     9         len=1;
    10         mt(s,0);
    11         int i=0;
    12         while(ch[i]=='0'&&ch[i]!=0) i++;
    13         if(ch[i]!=0) {
    14             len=strlen(ch)-i;
    15             for(i=0; i<len; i++) {
    16                 s[i]=ch[len-i-1]-48;
    17             }
    18         }
    19     }
    20     void print() { //输出
    21         int i=len-1;
    22         while(s[i]==0&&i>0) i--;
    23         for(; i>=0; i--) {
    24             printf("%d",s[i]);
    25         }
    26     }
    27     void add(int x) { //高精度加单精度
    28         int temp=0;
    29         s[0]+=x;
    30         while(s[temp]>9) {
    31             s[temp]-=10;
    32             temp++;
    33             s[temp]++;
    34         }
    35         if(s[len]!=0) len++;
    36     }
    37     void subtract(Hp a) { //高精度减高精度
    38         for(int i=0; i<len; i++) {
    39             s[i]-=a.s[i];
    40             if(s[i]<0) {
    41                 s[i]+=10;
    42                 s[i+1]--;
    43             }
    44         }
    45         while(len>1&&s[len-1]==0) len--;
    46     }
    47     void multiply(int b) { //高精度乘单精度
    48         int temp=0;
    49         for(int i=0; i<len; i++) {
    50             temp+=s[i]*b;
    51             s[i]=temp%10;
    52             temp/=10;
    53         }
    54         s[len++]=temp;
    55         while(s[len-1]>10) {
    56             s[len]+=s[len-1]/10;
    57             s[len-1]%=10;
    58             len++;
    59         }
    60         while(len>1&&s[len-1]==0) len--;
    61     }
    62     void multiply(Hp b) { //高精度乘高精度
    63         Hp c;
    64         mt(c.s,0);
    65         for(int i=0; i<len; i++) {
    66             for(int j=0; j<b.len; j++) {
    67                 c.s[i+j]+=s[i]*b.s[j];
    68                 c.s[i+j+1]+=c.s[i+j]/10;
    69                 c.s[i+j]%=10;
    70             }
    71         }
    72         len=len+b.len;
    73         for(int i=0; i<len; i++) {
    74             s[i]=c.s[i];
    75         }
    76         while(len>1&&s[len-1]==0) len--;
    77     }
    78 } A,B;
    79 char a[M];
    80 int main(){
    81     int t;
    82     while(~scanf("%d",&t)){
    83         int cas=1;
    84         while(t--){
    85             scanf("%s",a);
    86             A.init(a);
    87             B.init(a);
    88             A.multiply(B);
    89             A.multiply(8);
    90             B.multiply(7);
    91             A.subtract(B);
    92             A.add(1);
    93             printf("Case #%d: ",cas++);
    94             A.print();
    95             puts("");
    96         }
    97     }
    98     return 0;
    99 }
    View Code

     那个类似的题目被我找到了

    折线分割平面 http://acm.hdu.edu.cn/showproblem.php?pid=2050

    一样的解一元二次

     1 #include<cstdio>
     2 int main(){
     3     int t,n;
     4     while(~scanf("%d",&t)){
     5         while(t--){
     6             scanf("%d",&n);
     7             printf("%d
    ",2*n*n-n+1);
     8         }
     9     }
    10     return 0;
    11 }
    View Code

    end

  • 相关阅读:
    Rainmeter 雨滴桌面 主题分享
    行人检測之HOG特征(Histograms of Oriented Gradients)
    const和readonly差别
    ADB命令解析
    Java实现 蓝桥杯VIP 算法训练 接水问题
    Java实现 蓝桥杯VIP 算法训练 星际交流
    Java实现 蓝桥杯VIP 算法训练 星际交流
    Java实现 蓝桥杯VIP 算法训练 星际交流
    Java实现 蓝桥杯VIP 算法训练 星际交流
    Java实现 蓝桥杯VIP 算法训练 星际交流
  • 原文地址:https://www.cnblogs.com/gaolzzxin/p/3997021.html
Copyright © 2011-2022 走看看